下面的代码编译细跟g++ (GCC) 4.7.1 20120721
,但无法与最近建立clang version 3.2 (trunk)
。
struct Y {};
struct X {
operator const Y() const { return Y(); }
};
void f(Y&& y) {}
int main()
{
f(X());
return 0;
}
改变转换操作者operator Y() const
是足以使代码编译在两个编译器。
其编译器是在这种情况下,实际上是符合标准的? 什么是标准居然说这件事吗?
根据要求逐字错误:
bla.cpp:14:5: error: no viable conversion from 'X' to 'Y'
f(X());
^~~
bla.cpp:1:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'X' to
'const Y &' for 1st argument
struct Y {
^
bla.cpp:1:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'X' to
'Y &&' for 1st argument
struct Y {
^
bla.cpp:6:3: note: candidate function
operator const Y() const { return Y(); }
^
bla.cpp:10:12: note: passing argument to parameter 'y' here
void f(Y&& y) {}
^
编辑:不幸的是即使添加了过载
void f(const Y&) {}
还是让铛选择右值引用过载,因此这打破现有的代码,用来编译精细,例如用标准集装箱。
我相信铛是有权拒收此。 传递的参数f(Y&&)
需要两个转换步骤,第一个是你的operator const Y()
第二个是Y
的拷贝构造函数。 既算作用户定义的转换,我想,又都是隐式的,这违反了一个隐式转换序列仅包括一个用户定义的转换的原理。
这通过常量的值返回的目的是什么? 包含了一些有趣的见解返回的语义const T
。
嗯,如果我尝试添加过载void f(const Y&y)
作为编辑的问题,现在呢,铛表现相当strangly。 它仍然抱怨自己无法转换X
到Y
,甚至不列出过载f(const Y& y)
在其诊断。 但是,一旦我改变过载采取Y
由值,即写void f(const Y y)
它抱怨调用f
是暧昧。
这已经和Xcode 4.5的铛该报道Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
如果你能重现此与香草铛,你应该铛邮件列表上报告这个-当然似乎有潜伏的地方有一个bug ...
是形成不良的的例子。
有些N3242报价。
8.5.3第4段:
给定类型的“CV1 T1
”和“CV2 T2
”,“CV1 T1
”是参考有关“CV2 T2
”如果T1
是相同的类型T2
,或T1
是一个基类的T2
。 “CV1 T1
”是参考兼容“CV2 T2
”如果T1
是参考相关于T2
和CV1是相同的CV-资格,或更大的CV-资格比,CV2。
第5款(子弹标签是我的):
键入“CV1参考T1
”是通过类型“CV2的表达式初始化T2
”,如下所示:
- 如果参考是一个左值引用和...
否则,应参考是一个左值参照非易失性const型(即CV1应const
),或参考应一个rvalue参考。
一种。 如果初始化表达式
- 一世。 是一个x值,类prvalue,阵列prvalue或功能左值和“CV1
T1
”被参考兼容“CV2 T2
”,或 - II。 有一个类类型(即
T2
是一个类型),其中, T1
是不能引用相关于T2
,并且可以被隐式转换为x值,类prvalue,或类型“CV3的功能左值T3
”,其中“CV1 T1
”是参考兼容“CV3 T3
”, - 那么引用绑定到....
湾 否则,一个临时的型“CV1的T1
被创建”,并从使用用于非参考副本初始化(8.5)的规则初始化表达式初始化。 然后,将参考结合于暂时的。 如果T1
被参考相关到T2
,CV1应是相同的CV-资格,或更大的CV-资格比,CV2。 ...
对于函数参数初始化, T1
是Y
, T2
是X
,和CV1和CV2都为空。 图1是出:所述参考是一个rvalue参考,而不是左值参考。 2.ai是出: X
是不是参考兼容与Y
。 2.B. 是,因为复制初始化Y
从类型的prvalue X
包括两个用户定义的转换:转换函数,然后的拷贝构造Y
。 (确切的禁止是13.3.3.1p4。)
对于情况2.a.ii.,对于“CV3显而易见的选择T3
”是const Y
,但是这是没有好,因为Y
没有参考兼容与const Y
。 你可能会认为对于试图T3
是Y
和CV3是空的,但你又回到了需要的拷贝构造函数Y
作为第二隐含的用户定义的转换。