问题描述
我有一个编译器对一个小的C ++ 14代码片断不同意:
I have compilers disagreeing on a small C++14 code snippet:
#include <cassert>
struct unmovable {
unmovable() {}
unmovable(unmovable&&) = delete;
};
int main()
{
unmovable u;
auto i = [&]() -> decltype(auto) { return u; };
auto& uu = i();
assert(&uu == &u);
}
程序被g ++ 4.9.3,g ++ - 5.1接受。 0,g ++ - 5.2.0和VisualStudio 2015,但不是clang ++ - 3.7。
The program is accepted by g++4.9.3, g++-5.1.0, g++-5.2.0 and VisualStudio 2015, but not by clang++-3.7.
clang ++ - 3.7推导出返回类型为 unmovable
(值)而不是 unmovable&
。
clang++-3.7 deduces the return type to be unmovable
(value) and not unmovable&
.
变量 u
是全局变量,那么所有编译器都会同意这个错误。
If the program is changed slightly, so that the variable u
is global, then all compilers agree on the error.
u
在变量为本地时应为 unmovable&
类型。
As I understand it, the captured u
in the lambda should be of type unmovable&
when the variable is local.
我没有C ++ 14标准,但希望来自的草稿是相关的。我对7.1.6.2和7.1.6.4的解释是从返回的 decltype(auto)
变为 decltype(u)
,在全局情况下应该是 unmovable
(value),并且在局部 u
应成为 unmovable&
,因为捕获的变量必须是 unmovable&
类型。
I don't have the C++14 standard, but hopefully the draft from github is relevant. My interpretation of 7.1.6.2 and 7.1.6.4 is that decltype(auto)
becomes decltype(u)
from the return, which in the global case should be unmovable
(value) and in the lambda reference capture of the local u
, it should become unmovable&
since the captured variable must be of type unmovable&
. This would indicate that clang++ got it wrong.
如果我改变lambda和它的用法:
If I change the lambda and its use slightly:
auto i = [](auto& v) -> decltype(auto) { return v; };
auto& uu = i(u);
那么所有编译器都接受它,不管 u
是全局或局部的,我认为加强我对 decltype(auto)
扣除的解释,因为 v
确定变成 unmovable&
类型。
then all compilers accept it, regardless of whether u
is global or local, which I think strengthens my interpretation of the decltype(auto)
deduction, since v
here definitely becomes of type unmovable&
.
我的解释是否正确,因此clang ++不正确?
Is my interpretation correct and thus clang++ incorrect?
推荐答案
clang对我来说似乎是正确的。我同意你的解释,lambda返回类型必须 decltype(u)
,但不是 decltype(u)
unmovable&
。
clang seems correct to me. I agree with your interpretation that the lambda return type must be decltype(u)
, but not that decltype(u)
is unmovable&
.
18每个 id-expression em> lambda-expression 是由副本捕获的
实体的odr使用(3.2)转换为对
闭包类型的相应未命名数据成员的访问。 [注意:不是odr使用的 id-expression 是指原始实体,而不是封闭类型的成员。此外,这种 id-expression 不会导致实体的隐式捕获。
- end note ] [...]
18 Every id-expression within the compound-statement of a lambda-expression that is an odr-use (3.2) of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [ Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. Furthermore, such an id-expression does not cause the implicit capture of the entity. -- end note ] [...]
19每次出现 ))
其中[...]
19 Every occurrence of decltype((x))
where [...]
p19不适用,因为您有 decltype(u)
,而不是 decltype((u))
。
p19 doesn't apply, since you have decltype(u)
, not decltype((u))
.
p18然后说,由于 decltype(u)
中的 u
不是odr使用,所以它指的是
p18 then says that as the u
in decltype(u)
is not an odr-use, it refers to the original entity, it does not get transformed to an access of the member of the closure type.
但是,p19确实清楚地表明,如果你写你的 return
语句为
However, p19 does make it clear that if you write your return
statement as
auto i = [&]() -> decltype(auto) { return (u); };
那么lambda将返回 u
。如果这是您之后的行为,这将与clang一起工作。
then the lambda will return u
by reference. This will work with clang, if this is the behaviour you were after.
这篇关于decltype(auto)从lambda捕获推导的返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!