MSVC 19.29起条件表达式触发C2445错误:合法性及库作者指南
C++条件表达式歧义问题解答
1. 该程序是否合法?不合法的原因是什么?
这个程序不合法,核心原因是违反了C++标准对条件表达式(?:)的类型推导规则:
当条件表达式的两个分支操作数类型不同时,编译器必须找到一个公共目标类型,要求两个操作数都能通过隐式转换转换到该类型,且转换路径不能存在歧义。
在示例代码中:
- 分支
42(int类型)可通过X的非explicit构造函数隐式转换为X类型; - 分支
X(1729)(X类型)可通过operator int()转换函数隐式转换为int类型。
这两条转换路径均属于用户定义的隐式转换,而C++标准未规定这类转换的优先级,编译器无法确定选择哪条路径推导公共类型,因此产生歧义,属于标准明确禁止的格式错误。
2. 针对库作者的指导建议,以及explicit构造函数是否足够?
- 指导建议:对于同时提供可隐式转换的构造函数和反向类型转换函数的类(如示例中的
X、MFC的CStringT),必须避免双向隐式转换的设计,否则会触发类似的表达式歧义问题。 - 将构造函数声明为
explicit足够解决问题:
是的,修改后的X构造函数加上explicit修饰后:
此时struct X { explicit X(int) {} operator int() { return {}; } };int无法再通过隐式转换变为X类型,条件表达式的两个分支中仅存在X向int的隐式转换路径,编译器会明确将结果类型推导为int,歧义完全消除。
若需要更严格的类型安全,也可以将operator int()同样声明为explicit,但仅修改构造函数就足以解决当前场景的编译问题,同时保留了类向int的隐式转换能力(如果这是库的设计需求)。
内容的提问来源于stack exchange,提问作者Jabberwocky
相关产品推荐
相关产品推荐

