C++17 std::variant含bool时传指针给const引用无编译错误问题
问题原因核心:C++指针隐式转换规则 + std::variant的隐式构造特性
- 你调用
GetIndexOfVariant(PtrToVariant)时,传入的是StdVARIANT*类型的指针,而函数期望接收的是const StdVARIANT&类型。此时编译器会尝试两条可行路径:要么找到从StdVARIANT*到StdVARIANT的隐式转换规则构造临时对象,绑定到const引用上;要么类型完全不匹配触发编译错误。 - 当你的
StdVARIANT模板参数包含bool时:C++允许所有指针类型隐式转换为bool类型(空指针转换为false,非空指针转换为true)。此时编译器会自动完成隐式转换流程:先将指针转换为bool值,再用这个bool值构造一个临时的StdVARIANT对象,将这个临时对象绑定到函数的const引用参数上,因此编译不会报错。 - 当你移除
bool类型后:StdVARIANT剩下的可选类型均无法接收指针的隐式转换(指针不能隐式转换为整数、浮点数等类型),没有可行的构造路径,因此编译器直接抛出类型不匹配的错误。
运行结果异常的原因
你观察到的myvar->index()返回10、DoThing(myvar)返回11完全符合上述逻辑:
- 你给
*myvar赋值为double类型,double在你的variant可选列表中排在第11位(索引从0开始计算:0是std::monostate,1到10依次是各整数、浮点类型,第11位就是bool),因此myvar->index()返回10。 - 而
DoThing内部构造的临时variant存的是指针转换来的bool值,对应的索引就是11,因此返回11,和原对象的状态完全无关,属于典型的意料之外的隐式转换导致的逻辑错误。
规避方案
可以通过编译选项或代码约束避免这类问题:
- 开启GCC的
-Wbool-conversion或-Wconversion编译选项,会对指针隐式转换为bool的行为抛出警告,提前暴露问题。 - 如果业务不需要bool的隐式构造,可以自定义封装variant类型,将对应bool的构造函数声明为
explicit,禁止隐式转换。
内容的提问来源于stack exchange,提问作者Timothy John Laird
相关产品推荐
相关产品推荐

