以下代码正常工作:
#include <iostream> struct B { operator int() { return int(); } }; struct A { A(int, int){ std::cout << "A(int, int)" << std::endl; } }; A a({B(), B()}); int main() { }并产生输出:
A(int, int)DEMO
但我不明白为什么? 标准说的是:
但是,在13.3.1.3中调用复制/移动类复制初始化的第二步中的临时对象时,在考虑构造函数或用户定义的转换函数的参数时,初始值列表作为单个参数,或者当初始化符列表恰好具有一个元素,并且转换为某个类X或对(可能是cv-qualified)X的引用仅作为X构造函数的第一个参数考虑标准转换序列和省略号转换序列
所以在我们的例子中,我们考虑了构造函数的参数(它是{B(), B()} )。 更确切地说,我们通过初始化列表作为单个参数(我引用的规则中的第二个例子)。 现在,我们需要将initializer-list的第一个元素(类型B临时)转换为int ,唯一的方法是应用用户定义的转换( B::operator int() )。 但是,正如规则末尾所说,我只引用了标准转换序列和省略号转换序列 。 因为,该代码不应该工作,它应该抛出像A(int, int)这样的错误是不可行的或排序的。
怎么了。 可能是一个错误?
The following code works fine:
#include <iostream> struct B { operator int() { return int(); } }; struct A { A(int, int){ std::cout << "A(int, int)" << std::endl; } }; A a({B(), B()}); int main() { }and produces output:
A(int, int)DEMO
But I can't get why? What the Standard says is:
However, when considering the argument of a constructor or user-defined conversion function that is a candidate by 13.3.1.3 when invoked for the copying/moving of the temporary in the second step of a class copy-initialization, by 13.3.1.7 when passing the initializer list as a single argument or when the initializer list has exactly one element and a conversion to some class X or reference to (possibly cv-qualified) X is considered for the first parameter of a constructor of X [...] only standard conversion sequences and ellipsis conversion sequences are considered
So in our case we considered the argument of the constructor (it was {B(), B()}). More precisely, we passed initializer-list as a single argument (the second case in the rule I cited). Now, we need to convert the first element of the initializer-list (temporary of type B) to int and the only way to do that is to apply user-defined convertion (B::operator int()). But, as said at the end of rule that I cited only standard conversion sequences and ellipsis conversion sequences was considered. Since, that code shouldn't work, it should throw the error like A(int, int) is not viable or sort of.
What's wrong. May be it's a bug?
最满意答案
措辞有缺陷,并用C ++ 14改变。 现在[over.best.ics] / 4读取
但是,如果目标是
构造函数的第一个参数 [...]并且构造函数或用户定义的转换函数是一个候选者
13.3.1.3, 当参数是类复制初始化的第二步中的临时参数时 , 13.3.1.4,13.3.1.5或13.3.1.6(在所有情况下)或者 13.3.1.7的第二阶段,当初始化列表只有一个元素,目标是类X的构造函数的第一个参数,并且转换为X或引用(可能是cv-qualified) X ,不考虑用户定义的转换序列。 [ 注意:这些规则阻止在重载解析期间应用多个用户定义的转换,从而避免无限递归。 - 结束注释 ]
B()到int的转换不在此范围内 - 粗体短语仅适用于在复制初始化期间将引用绑定到临时对象。 但是, Clang根据上述拒绝了这个示例代码 :
class A; struct B { operator A(); }; struct A { A(A const&){} }; A a{B()};The wording was defective and changed with C++14. Now [over.best.ics]/4 reads
However, if the target is
the first parameter of a constructor or […]and the constructor or user-defined conversion function is a candidate by
13.3.1.3, when the argument is the temporary in the second step of a class copy-initialization, 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases), or the second phase of 13.3.1.7 when the initializer list has exactly one element, and the target is the first parameter of a constructor of class X, and the conversion is to X or reference to (possibly cv-qualified) X,user-defined conversion sequences are not considered. [ Note: These rules prevent more than one user-defined conversion from being applied during overload resolution, thereby avoiding infinite recursion. — end note ]
The conversion of B() to int is not covered by this - the bold phrase only appertains to the binding of a reference to a temporary during copy-initialization. However, Clang rejects this sample code according to the above:
class A; struct B { operator A(); }; struct A { A(A const&){} }; A a{B()};更多推荐
发布评论