consteval函数可接收空类对象吗?多编译器编译分歧谁正确?
C++即时函数参数的编译器行为分歧
以下是测试代码:
struct Foo { consteval auto operator+(Foo) const noexcept { return Foo{}; } }; struct Bar : Foo {}; Foo func() { Bar foo, bar; return foo + bar; }
上述代码中Foo是空类,可通过GCC和Clang编译,但无法通过MSVC编译。MSVC提示bar不是常量表达式,不能作为即时函数operator+的参数,而GCC和Clang无此报错。请问哪款编译器的处理符合C++标准?
结论:GCC与Clang的处理符合C++标准
根据C++标准,调用consteval函数时,实参必须是常量表达式。这里的关键在于:Bar类型的对象foo和bar在传递给operator+(参数类型为Foo)时,会触发隐式的复制初始化转换。对于空类Foo来说,这种转换是完全平凡的——没有任何需要运行时计算的操作,转换后的结果属于常量表达式范畴。
MSVC的错误在于误判了这种隐式转换的性质,错误地认为Bar对象无法转换为符合要求的常量表达式实参。而GCC和Clang正确识别了该平凡转换满足常量表达式的要求,因此编译行为符合C++标准。
内容的提问来源于stack exchange,提问作者Timothy Liu
相关产品推荐
相关产品推荐

