转换为"const Y"不适用于 clang 上的"R&&"
Conversion to `const Y` not applicable for `R&&` on clang
下面的代码可以用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段:
给定类型">cv1
T1
"和">cv2T2
",">cv1T1
"与">cv2T2
"的引用相关,如果T1
与T2
的类型相同,或者T1
是T2
的基类。简历1T1
"与">CV2T2
"的参考文献兼容,如果T1
与T2
的参考文献相关,并且CV1与CV2的简历资格相同,或比CV2更符合CV资格。
第5段(项目符号标签是我的):
对类型">cv1
T1
"的引用由类型">cv2T2
"的表达式初始化,如下所示:
- 如果引用是左值引用并且...
否则,引用应为非易失性常量类型的左值引用(即cv1应为
const
),或者引用应为右值引用。一个。如果初始值设定项表达式
- i. 是 xValue、类 PRv、数组 PrValue 或函数 lvalue,并且 ">CV1
T1
" 与 ">CV2T2
" 的引用兼容,或- ii. 具有类类型(即
T2
是一个类类型),其中T1
与T2
无关,并且可以隐式转换为类型为 "cv3T3
" 的 xvalue、class prvalue 或函数 lvalue,其中 "cv1T1
" 与 ">cv3T3
" 引用兼容,- 那么引用绑定到....
b. 否则,将使用非引用复制初始化规则 (8.5) 从初始值设定项表达式创建并初始化类型为">cv1
T1
"的临时。 然后将引用绑定到临时引用。 如果T1
与T2
参考文献相关,则cv1应与cv2具有相同的简历资格,或比cv2具有更高的简历资格。 ...
对于函数参数初始化,T1
Y
,T2
X
,cv1和cv2均为空。 1 is out:引用是右值引用,而不是左值引用。 2.a.i. 已出局:X
与Y
不兼容。 2.b. 已退出,因为从类型X
的 prvalue 复制初始化Y
涉及两个用户定义的转换:转换函数,然后是Y
的复制构造函数。 (确切的禁止在 13.3.3.1p4 中。
对于情况2.a.ii.,">cv3T3
"的明显选择是const Y
,但这不好,因为Y
与const Y
不兼容。 你可能会争辩说尝试T3
是Y
而cv3是空的,但随后你又回到需要Y
的复制构造函数作为第二个隐式用户定义转换。
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 结构化绑定初始值设定项表单 { 赋值表达式 } 对于 clang 上的数组类型失败
- Clang编译器不支持aarch64-apple-darwin上的-fxray-instrument
- Mac Snow Leopard 上的 Qt 5.3.2:ld:在架构x86_64 [clang、Objective-C
- 新行上的 clang 格式右括号
- clang-tidy 忽略 Windows 上的可读性标识符命名
- Windows 上的 Clang/LLVM 7 和 8 多次初始化内联静态数据成员(使用 link.exe 和 lld-
- l值引用对象上的Constexpr成员函数:Clang和gcc不同意
- 在不合格的呼叫上,Clang和GCC上的错误
- 原始数组和 std::array 在 clang++ 和 VC++ 上的不同迭代器行为
- 仅在 2 的幂上错过了 clang 中的优化
- C++ 异常绕过 clang/llvm 上的捕获
- 从std::map派生的类不在Visual C++上编译(但在gcc和clang上编译)
- GCC/Clang上的模板错误,但在MSVC上没有错误
- ConstexPR静态模板功能:G 错误是Clang上的警告
- 转换为"const Y"不适用于 clang 上的"R&&"
- 不同的输出调用clang上的malloc应用编译器选项-00和-03
- 引发异常导致OSX 10.11.4+clang上的SIGSEGV
- 阐述类型指的是Clang上的类型定义错误
- 完全专用模板的constexpr静态成员在CLang上的动态链接失败