列表初始化引用:GCC/MSVC接受Clang拒绝,标准规定的正确行为?
C++标准下该代码的正确行为判定
以下代码可通过GCC、MSVC和EDG编译,但被Clang拒绝:
struct X { public: X(){} }; struct Y : X { }; struct Z { public: operator const Y () const { return {}; } }; int main() { Z z; X&& r{z}; //Clang: 拒绝编译, gcc: 通过, msvc: 通过, Edg: 通过 }
Clang给出的错误信息如下:
<source>:22:11: error: no viable conversion from 'Z' to 'X' 22 | X&& r{z}; //Clang: 拒绝编译, gcc: 通过, msvc: 通过, Edg: 通过 | ^ <source>:2:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Z' to 'const X &' for 1st argument 2 | struct X | ^ <source>:2:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'Z' to 'X &&' for 1st argument 2 | struct X | ^ <source>:14:9: note: candidate function 14 | operator const Y () const | ^ <source>:2:8: note: passing argument to parameter here 2 | struct X | ^
依据最新C标准(C20及后续版本),此场景下的正确行为是程序应当被编译器接受。具体标准规则依据:
- 初始化
X&& r{z}时,允许走合法的转换序列:先通过Z的转换运算符将z转换为const Y临时对象; - 派生类临时对象可通过标准转换转为基类类型,且该临时对象能够绑定到基类的右值引用
X&&; - 上述转换路径符合C++标准中引用初始化的规则,编译器应认可该代码的合法性。
内容的提问来源于stack exchange,提问作者Anoop Rana
相关产品推荐
相关产品推荐

