这个程序no longer compiles在 /std:c++20
1 下,从 MSVC 19.29 (VS16.11) 开始:
struct X {
X(int) {}
operator int() { return {}; }
};
int main() {
true ? 42 : X(1729);
}
编译器诊断读取:
error C2445: result type of conditional expression is ambiguous: types 'int' and 'X' can be converted to multiple common types note: could be 'int' note: or 'X'
这似乎是合理的,因为 X
实现了一个可以从 int
隐式转换为 X
的转换构造函数,以及一个用户定义的转换函数可以从 X
隐式转换为 int
。
编译器似乎也同意这一点:
<source>:7:10: error: operands to '?:' have different types 'int' and 'X' 7 | true ? 42 : X(1729); | ~~~~~^~~~~~~~~~~~~~ <source>:7:10: note: and each type can be converted to the other
<source>:7:10: error: conditional expression is ambiguous; 'int' can be converted to 'X' and vice versa 7 | true ? 42 : X(1729); | ^ ~~ ~~~~~~~
问题
这是一个有效的 C++ 程序吗?如果不是,为什么不呢?
奖励问题
对库作者的指导是什么2?正在explicit
关于施工足够吗?如果是这样,为什么?
1 这用于在 previous versions 中编译使用 /permissive
compiler option 时仍然如此.
2 X
与 MFC 的 CStringT
具有相同的属性类模板。
最佳答案
是的,根据[expr.cond]/4这是不明确的因为隐式转换序列可以从 :
操作数到另一个类型形成。这些转化序列没有应用排名。
C++20 之前的 MSVC 隐式使用 /permissive
,这使得一些行为不符合标准,这似乎也发生在这里。
可以通过使构造函数或转换函数显式
来避免此特定问题,在这种情况下,它不能在隐式转换序列中使用。
通常,如果没有充分的理由表明等效的普通成员函数调用不够,我建议避免使用转换函数。
我还建议将构造函数和转换函数都显式
,除非您想让用户这样做,例如:将 int
传递给采用 X
的函数,或将 X
传递给需要 int
的函数,这是有意义的显然,用户假设该函数采用其他类型。对于 int
和字符串类型来说,情况肯定不是这样的。
如果构造函数和转换函数都是显式的,那么条件运算符将再次失败,这次是因为无法形成转换序列。但我认为这很好。字符串和 int 并不等同。用户应明确说明他们想要哪种类型。
关于c++ - 从 MSVC 19.29 (VS16.11) 开始,条件运算符表达式出现问题 C2445,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77347997/