rya*_*ner 18 c++ clang visual-c++ overload-resolution implicit-conversion
这个例子似乎用VC10和gcc编译(虽然我的gcc版本很老).
编辑:R.Martinho Fernandez在gcc 4.7上试过这个并且行为仍然是一样的.
struct Base
{
operator double() const { return 0.0; }
};
struct foo
{
foo(const char* c) {}
};
struct Something : public Base
{
void operator[](const foo& f) {}
};
int main()
{
Something d;
d["32"];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但克朗抱怨道:
test4.cpp:19:6: error: use of overloaded operator '[]' is ambiguous (with operand types 'Something' and 'const char [3]')
d["32"]
~^~~~~
test4.cpp:13:10: note: candidate function
void operator[](const foo& f) {}
^
test4.cpp:19:6: note: built-in candidate operator[](long, const char *)
d["32"]
^
test4.cpp:19:6: note: built-in candidate operator[](long, const restrict char *)
test4.cpp:19:6: note: built-in candidate operator[](long, const volatile char *)
test4.cpp:19:6: note: built-in candidate operator[](long, const volatile restrict char *)
Run Code Online (Sandbox Code Playgroud)
重载决议考虑了这个表达式,考虑了两个可能的函数:
如果我写d["32"]了d.operator[]("32"),那么重载解析甚至不会看第2个选项,而clang也会编译好.
编辑:(澄清问题)
这似乎是重载决策中的一个复杂区域,因此我非常感谢在这种情况下详细解释过载分辨率的答案,并引用标准(如果有一些模糊/高级可能是未知规则) .
如果铿锵是正确的,我也有兴趣知道为什么这两个是模棱两可的/一个不优于另一个.答案可能需要解释重载决策如何考虑两个候选者所涉及的隐式转换(用户定义和标准转换)以及为什么一个不比另一个好.
注意:如果operator double()更改为operator bool(),则所有三个(clang,vc,gcc)将拒绝编译时出现类似的模糊错误.
Xeo*_*Xeo 12
通过逐步完成重载分辨率,应该更容易理解为什么重载决策是模糊的.
§13.5.5 [over.sub]
因此,对于类型的类对象(如果存在)以及如果通过重载解析机制(13.3.3)将运算符选择为最佳匹配函数,则将下标表达式
x[y]解释为.x.operator[](y)xTT::operator[](T1)
现在,我们首先需要一个重载集.这是根据§13.3.1并包含成员以及非成员函数构建的.请参阅我的这个答案以获得更详细的解释.
§13.3.1 [over.match.funcs]
p2候选函数集可以包含要针对同一参数列表解析的成员函数和非成员函数.因此,参数和参数列表在此异构集中是可比较的,成员函数被认为具有额外的参数,称为隐式对象参数,其表示已为其调用成员函数的对象.[...]
p3类似地,在适当的情况下,上下文可以构造一个参数列表,其中包含一个隐含的对象参数来表示要操作的对象.
// abstract overload set (return types omitted since irrelevant)
f1(Something&, foo const&); // linked to Something::operator[](foo const&)
f2(std::ptrdiff_t, char const*); // linked to operator[](std::ptrdiff_t, char const*)
f3(char const*, std::ptrdiff_t); // linked to operator[](char const*, std::ptrdiff_t)
Run Code Online (Sandbox Code Playgroud)
然后,构造一个参数列表:
// abstract argument list
(Something&, char const[3]) // 'Something&' is the implied object argument
Run Code Online (Sandbox Code Playgroud)
然后针对重载集的每个成员测试参数列表:
f1 -> identity match on argument 1, conversion required for argument 2
f2 -> conversion required for argument 1, conversion required for argument 2 (decay)
f3 -> argument 1 incompatible, argument 2 incompatible, discarded
Run Code Online (Sandbox Code Playgroud)
然后,由于我们发现需要隐式转换,我们来看看§13.3.3 [over.match.best] p1:
定义
ICSi(F)如下:
- if
F是静态成员函数,[...]; 除此以外,- let
ICSi(F)表示将i列表中的i-th参数转换为可行函数的-th参数类型的隐式转换序列F.13.3.3.1定义了隐式转换序列,13.3.3.2定义了一个隐式转换序列比另一个更好的转换序列或更差转换序列的含义.
现在让我们为重载集()中的f1和构造隐式转换序列:f2§13.3.3.1
ICS1(f1): 'Something&' -> 'Someting&', standard conversion sequence
ICS2(f1): 'char const[3]' -> 'foo const&', user-defined conversion sequence
ICS1(f2): 'Something&' -> 'std::ptrdiff_t', user-defined conversion sequence
ICS2(f2): 'char const[3]' -> 'char const*', standard conversion sequence
Run Code Online (Sandbox Code Playgroud)
§13.3.3.2 [over.ics.rank] p2
标准转换序列(13.3.3.1.1)是比用户定义的转换序列或省略号转换序列更好的转换序列.
因此ICS1(f1)比ICS1(f2)并且ICS2(f1)更糟糕ICS2(f2).
相反,ICS1(f2)比...更糟糕ICS1(f1),ICS2(f2)也更好ICS2(f1).
§13.3.3 [over.match.best]
p1(续)鉴于这些定义,如果对于所有参数,可行函数
F1被定义为比另一个可行函数更好的函数,不是比转换序列更差,然后[...]F2iICSi(F1)ICSi(F2)p2如果只有一个可行函数比所有其他可行函数更好的函数,则它是由重载决策选择的函数; 否则电话会形成不良.
好吧,f*ck.:)因此,Clang拒绝该代码是正确的.
| 归档时间: |
|
| 查看次数: |
1630 次 |
| 最近记录: |