mingw vs msvc关于字符串文字的隐式转换
mingw vs msvc on implicit conversion of string literals
我有一个 std::variant
不同类型,包括 int32_t
、int64_t
、float
、double
、std::string
和 bool
.
当我分配一个字符串文字(const char*
,此变体中不存在)时,我假设它将隐式转换为 std::string
,并且它按我预期的方式工作 MinGW (9.0.0 64-bit)
。但是使用 MSVC (2019 64-bit)
它隐式转换为 bool
。
如果我明确地将它转换为 std::string 然后将它分配给 variant 它在两个编译器上都可以正常工作。
这是代码
#include <iostream>
#include <variant>
#if defined(__MINGW64__) || defined(__MINGW32__)
#define CMP_NAME "[ MinGW ]"
#elif defined(_MSC_VER)
#define CMP_NAME "[ MSVC ]"
#else
#define CMP_NAME "[ Others ]"
#endif
using KInt32 = int32_t;
using KInt64 = int64_t;
using KFloat = float;
using KDouble = double;
using KString = std::string;
using KBoolean = bool;
using Variant = std::variant<
KInt32 /*0*/,
KInt64 /*1*/,
KFloat /*2*/,
KDouble /*3*/,
KString /*4*/,
KBoolean /*5*/
>;
int main()
{
//passing a const char* to Variant [target is to initialize as KString]
Variant var = "ABCDE";
std::cout << "Build With Compiler Set " CMP_NAME << std::endl;
std::cout << "index = " << var.index() << std::endl;
try{
KString &str = std::get<KString>(var);
std::cout << "\t[string = " << str << "]" << std::endl;
}
catch(const std::exception &e){
std::cout << "\t[exception = " << e.what() << "]" << std::endl;
}
return 0;
}
这是输出
使用 MinGW 9.0.0
Build With Compiler Set [ MSVC ]
index = 5
[exception = bad variant access]
使用 MSVC 2019
Build With Compiler Set [ MinGW ]
index = 4
[string = ABCDE]
索引 4 表示 KString
(又名 std::string
),索引 5 表示 KBoolean
(又名 bool
)。
所以我的问题是为什么两个编译器给出不同的结果?
在 C++20 中,对于这种情况,变体的行为发生了变化。
有关更长时间的讨论,请参阅 。
看起来像是标准库中的错误,已修复。
我写过这个测试:
#include "catch2/catch_all.hpp"
#include <variant>
TEST_CASE("std::variant literal conversion") {
std::variant<int, double, std::string, bool> var;
CHECK(var.index() == 0);
var = 1;
CHECK(var.index() == 0);
CHECK(std::holds_alternative<int>(var));
var = 1.0;
CHECK(var.index() == 1);
CHECK(std::holds_alternative<double>(var));
var = std::string{"foo"};
CHECK(var.index() == 2);
CHECK(std::holds_alternative<std::string>(var));
var = true;
CHECK(var.index() == 3);
CHECK(std::holds_alternative<bool>(var));
var = "foo";
CHECK(var.index() == 2);
CHECK(std::holds_alternative<std::string>(var));
}
它在 GCC 9.4 和 Clang 10.0.1 上失败,在 GCC 10.1 和 Clang 11.0 上没问题。
我有一个 std::variant
不同类型,包括 int32_t
、int64_t
、float
、double
、std::string
和 bool
.
当我分配一个字符串文字(const char*
,此变体中不存在)时,我假设它将隐式转换为 std::string
,并且它按我预期的方式工作 MinGW (9.0.0 64-bit)
。但是使用 MSVC (2019 64-bit)
它隐式转换为 bool
。
如果我明确地将它转换为 std::string 然后将它分配给 variant 它在两个编译器上都可以正常工作。
这是代码
#include <iostream>
#include <variant>
#if defined(__MINGW64__) || defined(__MINGW32__)
#define CMP_NAME "[ MinGW ]"
#elif defined(_MSC_VER)
#define CMP_NAME "[ MSVC ]"
#else
#define CMP_NAME "[ Others ]"
#endif
using KInt32 = int32_t;
using KInt64 = int64_t;
using KFloat = float;
using KDouble = double;
using KString = std::string;
using KBoolean = bool;
using Variant = std::variant<
KInt32 /*0*/,
KInt64 /*1*/,
KFloat /*2*/,
KDouble /*3*/,
KString /*4*/,
KBoolean /*5*/
>;
int main()
{
//passing a const char* to Variant [target is to initialize as KString]
Variant var = "ABCDE";
std::cout << "Build With Compiler Set " CMP_NAME << std::endl;
std::cout << "index = " << var.index() << std::endl;
try{
KString &str = std::get<KString>(var);
std::cout << "\t[string = " << str << "]" << std::endl;
}
catch(const std::exception &e){
std::cout << "\t[exception = " << e.what() << "]" << std::endl;
}
return 0;
}
这是输出
使用 MinGW 9.0.0
Build With Compiler Set [ MSVC ]
index = 5
[exception = bad variant access]
使用 MSVC 2019
Build With Compiler Set [ MinGW ]
index = 4
[string = ABCDE]
索引 4 表示 KString
(又名 std::string
),索引 5 表示 KBoolean
(又名 bool
)。
所以我的问题是为什么两个编译器给出不同的结果?
在 C++20 中,对于这种情况,变体的行为发生了变化。
有关更长时间的讨论,请参阅
看起来像是标准库中的错误,已修复。
我写过这个测试:
#include "catch2/catch_all.hpp"
#include <variant>
TEST_CASE("std::variant literal conversion") {
std::variant<int, double, std::string, bool> var;
CHECK(var.index() == 0);
var = 1;
CHECK(var.index() == 0);
CHECK(std::holds_alternative<int>(var));
var = 1.0;
CHECK(var.index() == 1);
CHECK(std::holds_alternative<double>(var));
var = std::string{"foo"};
CHECK(var.index() == 2);
CHECK(std::holds_alternative<std::string>(var));
var = true;
CHECK(var.index() == 3);
CHECK(std::holds_alternative<bool>(var));
var = "foo";
CHECK(var.index() == 2);
CHECK(std::holds_alternative<std::string>(var));
}
它在 GCC 9.4 和 Clang 10.0.1 上失败,在 GCC 10.1 和 Clang 11.0 上没问题。