为何GCC10及以上版本拒绝std::variant构造函数的隐式转换?
std::variant隐式转换的编译器版本差异问题
示例代码
#include <vector> #include <variant> #include <stdint.h> using KFPGAData = std::variant<uint16_t>; int main(int,char**) { int v = 10; KFPGAData d = v; return 0; }
问题现象
使用GCC编译器以-std=c++17标准编译时:
- GCC 9版本编译通过
- GCC 10及以上版本编译失败,报错信息如下:
<source>:11:19: error: conversion from 'int' to non-scalar type 'KFPGAData' {aka 'std::variant<short unsigned int>'} requested 11 | KFPGAData d = v; | ^
同时高版本的MSVC和Clang编译器编译该代码时也会出现类似错误。
原因分析
这是因为GCC9对std::variant的构造实现存在不符合C++17标准的宽松处理,后续版本以及其他主流编译器则严格遵循了标准规定。
C++17标准明确要求,std::variant的隐式构造函数仅允许无窄化的隐式转换。这里将int类型的v赋值给std::variant<uint16_t>,本质是要把int隐式转换为uint16_t——即便数值10在uint16_t的范围内,这种转换仍属于标准定义的窄化转换,因此不允许通过隐式转换来构造std::variant。
GCC9错误地放宽了这一限制,允许了此类窄化转换的隐式构造;而后续的GCC版本修复了这个实现缺陷,严格执行标准,所以编译报错。高版本的MSVC和Clang从一开始就严格遵循标准,因此同样会触发错误。
修复方案
通过显式转换明确类型,避免窄化转换的隐式构造:
KFPGAData d = static_cast<uint16_t>(v);
内容的提问来源于stack exchange,提问作者libgcc
相关产品推荐
相关产品推荐

