Fed*_*dor 11 c++ language-lawyer overload-resolution implicit-conversion
在以下代码中,struct A有两个隐式转换运算符到char和int,并且将结构体的实例与整数常量进行比较2:
struct A {
constexpr operator char() { return 1; }
constexpr operator int() { return 2; }
};
static_assert( A{} == 2 );
Run Code Online (Sandbox Code Playgroud)
代码在 GCC 和 MSVC 中顺利通过,但 Clang 抱怨:
<source>:5:20: error: use of overloaded operator '==' is ambiguous (with operand types 'A' and 'int')
static_assert( A{} == 2 );
~~~ ^ ~
<source>:5:20: note: because of ambiguity in conversion of 'A' to 'float'
<source>:2:15: note: candidate function
constexpr operator char() { return 1; }
^
<source>:3:15: note: candidate function
constexpr operator int() { return 2; }
^
<source>:5:20: note: built-in candidate operator==(float, int)
static_assert( A{} == 2 );
^
<source>:5:20: note: built-in candidate operator==(double, int)
<source>:5:20: note: built-in candidate operator==(long double, int)
<source>:5:20: note: built-in candidate operator==(__float128, int)
<source>:5:20: note: built-in candidate operator==(int, int)
...
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/h9Kd66heM
一般问题是这里哪个编译器?尤其有趣的是,为什么 Clang 不喜欢operator==(int, int),而是将其列出来?
Bri*_*ian 14
这是CWG 507。给出了一个与您类似的例子,提交者解释说,根据标准,重载解析是不明确的,尽管这个结果非常违反直觉。
转换到您的特定示例,在比较operator==(int, int)并operator==(float, int)确定哪个是更好的候选者时,我们必须确定哪个对第一个参数具有更好的隐式转换序列(显然在第二个参数中,不需要转换)。对于 的第一个参数operator==(int, int),我们只使用A::operator int. 对于 的第一个参数operator==(float, int),无法决定是否使用A::operator intor A::operator char,因此我们得到“不明确的转换序列”。重载解析规则规定,不明确的转换序列并不比任何其他用户定义的转换序列更好或更差。A{}因此,从到int(通过)的直接转换A::operator int并不被认为比从A{}到的模糊转换更好float。这意味着两者都不是operator==候选人都不比另一位更好。
Clang 显然遵循了标准的文字,而 GCC 和 MSVC 可能正在做其他事情,因为标准似乎在这里被破坏了。“哪个编译器是正确的”取决于您对标准应该说什么的看法。问题页面上没有建议的解决方案。
我建议删除operator char除非你真的非常需要它,在这种情况下你将不得不考虑你还愿意放弃什么。
| 归档时间: |
|
| 查看次数: |
391 次 |
| 最近记录: |