为何std::variant在GCC 8.5与12.1中对const char*字面量表现不同?
#include <iostream> #include <string> #include <variant> int main() { std::variant<std::string, bool> v{ "hasta la vista" }; std::cout << std::boolalpha << std::holds_alternative<std::string>(v) << ' ' << std::holds_alternative<bool>(v) << std::endl; }
GCC 12.1.1
$ g++ std_alternative.cpp $ ./a.out true false
GCC 8.5.0
$ g++ -std=c++17 std_alternative.cpp $ ./a.out false true
输出差异原因
这是由于不同版本GCC对std::variant初始化时的重载解析逻辑不同导致的:
- 字符串字面量
"hasta la vista"的类型是const char*,初始化std::variant<std::string, bool>时,存在两个可选路径:一是通过const char*构造std::string(用户定义转换),二是将非空指针隐式转换为bool(标准转换)。 - GCC 8.5.0错误地判定指针转
bool的优先级更高,因此variant被初始化为bool类型;GCC 12.1.1修复了这个问题,正确选择了更匹配的std::string构造路径。
符合C++17标准的行为
GCC 12.1.1的行为符合C++17标准。根据标准规则,std::variant初始化会选择最佳匹配的类型:const char*到std::string的转换属于用户定义转换,优先级高于指针到bool的标准转换序列,因此variant应被初始化为std::string类型。
跨版本一致的修改方案
通过显式构造std::string消除重载歧义,让两个版本都明确选择std::string类型:
#include <iostream> #include <string> #include <variant> int main() { std::variant<std::string, bool> v{ std::string("hasta la vista") }; // 也可以使用C++14引入的字符串字面量后缀:v = "hasta la vista"s; std::cout << std::boolalpha << std::holds_alternative<std::string>(v) << ' ' << std::holds_alternative<bool>(v) << std::endl; }
修改后两个GCC版本的输出都会是true false。
内容的提问来源于stack exchange,提问作者user7610
相关产品推荐
相关产品推荐

