转换为"const Y"不适用于 clang 上的"R&&"

Conversion to `const Y` not applicable for `R&&` on clang

本文关键字:clang 上的 适用于 不适用 const 转换      更新时间:2023-10-16

下面的代码可以用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&) {}

仍然让 clang 选择右值引用重载,所以这个 破坏用于精细编译的现有代码,例如使用标准 器皿。

我相信clang拒绝这一点是正确的。将参数传递给f(Y&&)需要两个转换步骤,第一个是operator const Y(),第二个是Y的复制构造函数。我认为两者都算作用户定义的转换,而且都是隐式的,这违反了隐式转换序列仅包括一个用户定义的转换的原则。

这个按常量值返回的目的?包含了一些关于返回const T语义的有趣见解。

嗯,如果我尝试像现在编辑的问题那样添加一个重载void f(const Y&y),clang的行为非常激烈。它仍然抱怨无法将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)。如果你可以用香草叮当声重现这一点,你可能应该在叮当邮件列表中报告这个 - 当然似乎有一个错误潜伏在某个地方......

该示例格式不正确。

一些 N3242 报价。

8.5.3 第4段:

给定类型">cv1T1"和">cv2T2",">cv1T1"与">cv2T2"的引用相关,如果T1T2的类型相同,或者T1T2的基类。简历1T1"与">CV2T2"的参考文献兼容,如果T1T2的参考文献相关,并且CV1与CV2的简历资格相同,或比CV2更符合CV资格。

第5段(项目符号标签是我的):

对类型">cv1T1"的引用由类型">cv2T2"的表达式初始化,如下所示:

  1. 如果引用是左值引用并且...
  2. 否则,引用应为非易失性常量类型的左值引用(即cv1应为const),或者引用应为右值引用。

    一个。如果初始值设定项表达式

    • i. 是 xValue、类 PRv、数组 PrValue 或函数 lvalue,并且 ">CV1T1" 与 ">CV2T2" 的引用兼容,或
    • ii. 具有类类型(即T2是一个类类型),其中T1T2无关,并且可以隐式转换为类型为 "cv3T3" 的 xvalue、class prvalue 或函数 lvalue,其中 "cv1T1" 与 ">cv3T3" 引用兼容,
    • 那么引用绑定到....

    b. 否则,将使用非引用复制初始化规则 (8.5) 从初始值设定项表达式创建并初始化类型为">cv1T1"的临时。 然后将引用绑定到临时引用。 如果T1T2参考文献相关,则cv1应与cv2具有相同的简历资格,或比cv2具有更高的简历资格。 ...

对于函数参数初始化,T1YT2X,cv1cv2均为空。 1 is out:引用是右值引用,而不是左值引用。 2.a.i. 已出局:XY不兼容。 2.b. 已退出,因为从类型X的 prvalue 复制初始化Y涉及两个用户定义的转换:转换函数,然后是Y的复制构造函数。 (确切的禁止在 13.3.3.1p4 中。

对于情况2.a.ii.,">cv3T3"的明显选择是const Y,但这不好,因为Yconst Y不兼容。 你可能会争辩说尝试T3Ycv3是空的,但随后你又回到需要Y的复制构造函数作为第二个隐式用户定义转换。