You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:54:31