Łuk*_*ski 7 c++ gcc return clang language-lawyer
最近有一个恭维问题,由此片段说明:
struct Base
{
};
template<typename T>
struct A : Base
{
A(){}
A(Base&&) {}
};
A<int> foo()
{
A<double> v;
return v;
}
int main()
{
auto d = foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Gcc说没关系,但是clang不同意并说"候选构造函数不可行:第一个参数A(Base &&){}"没有已知的从'A'到'Base &&'的转换,请亲自看看:https://godbolt.org/Z/Y7mwnU
任何一种读者是否能够帮助支持任何一种观点?
clang在这里是正确的。提交87530。
\nreturn 语句的规则是[class.copy.elision]/3:
\n\n\n在以下复制初始化上下文中,可能会使用移动操作而不是复制操作:
\n\n
\n- 如果语句
\nreturn([stmt.return]) 中的表达式是一个(可能带括号的)id 表达式,它命名一个对象,该对象具有在最内层封闭函数或lambda 表达式的主体或参数声明子句中声明的自动存储持续时间,或者- 如果throw 表达式的操作数是非易失性自动对象的名称(函数或catch 子句参数除外)除外),其范围不超出最内层封闭 try 块的末尾(如果有一个) ,
\n首先执行重载决策来选择副本的构造函数,就好像该对象是由右值指定的一样。如果第一个重载决策失败或未执行,或者所选构造函数的第一个参数的类型不是对象类型的右值引用(可能是 cv 限定的),则再次执行重载决策,同时考虑对象作为左值。[\xe2\x80\x89注意:无论是否发生复制省略,都必须执行此两阶段重载决策。如果不执行省略,它确定要调用的构造函数,并且即使省略调用,所选构造函数也必须可访问。\xe2\x80\x94\xe2\x80\x89尾注\xe2\x80\x89]
\n
强调我的。
\n我们遇到了第一点,我们返回一个命名非易失性自动对象的id 表达式。因此,我们将重载解析视为右值。此重载解析成功,有一个构造函数采用Base&&. 不过,请注意粗体部分。该参数的类型不是类型的右值引用。
因此,我们再次尝试将该对象视为左值。此重载决策失败。
\n因此,该程序格式不正确。
\n| 归档时间: |
|
| 查看次数: |
182 次 |
| 最近记录: |