C++ decltype(自动)从lambda捕获推断出的返回类型
我有一些编译器不同意一个小的C++14代码段:C++ decltype(自动)从lambda捕获推断出的返回类型,c++,c++11,lambda,c++14,decltype,C++,C++11,Lambda,C++14,Decltype,我有一些编译器不同意一个小的C++14代码段: #include <cassert> struct unmovable { unmovable() {} unmovable(unmovable&&) = delete; }; int main() { unmovable u; auto i = [&]() -> decltype(auto) { return u; }; auto& uu = i(); assert
#include <cassert>
struct unmovable {
unmovable() {}
unmovable(unmovable&&) = delete;
};
int main()
{
unmovable u;
auto i = [&]() -> decltype(auto) { return u; };
auto& uu = i();
assert(&uu == &u);
}
然后所有编译器都接受它,不管u
是全局的还是局部的,我认为这加强了我对decltype(auto)
推断的解释,因为v
在这里肯定变成了不可移动的类型&
我的解释正确吗?因此,铿锵++不正确吗?在我看来,铿锵似乎是正确的。我同意您的解释,即lambda返回类型必须是
decltype(u)
,但不是decltype(u)
是不可移动的&
5.1.2 Lambda表达式[expr.prim.Lambda]
18 lambda表达式的component语句中的每个id表达式都是
副本捕获的实体被转换为对副本的相应未命名数据成员的访问
闭合类型。[注意:非odr用途的id表达式引用原始实体,而不是闭包类型的成员。此外,此类id表达式不会导致实体的隐式捕获。
--结束说明][…]
19每次出现decltype((x))
where[…]
p19不适用,因为您有decltype(u)
,而不是decltype((u))
p18接着说,由于decltype(u)
中的u
不是odr用法,它指的是原始实体,因此不会转换为闭包类型成员的访问
然而,第19页明确指出,如果您将return
语句编写为
auto i = [&]() -> decltype(auto) { return (u); };
然后lambda将通过引用返回
u
。这将适用于clang,如果这是您所追求的行为。在lambda中,decltype(u)
指的是捕获的实体,而不是闭包的任何数据成员。参见[expr.prim.lambda]p19,但gcc的行为似乎不一致:@dyp[expr.prim.lambda]p19是关于decltype((u))
,而不是关于decltype(u)
decltype
是一种罕见的情况,在这种情况下,看似多余的括号可以起到作用。@hvd Yes,[expr.prim.lambda]p19是关于decltype((u))
,但它增加了特殊处理。如果没有这个特殊规则,decltype(u)
不是u
的odr用法,也会引用捕获的实体。编辑-阅读您的答案后,我们似乎同意;所以这只是一个误解?另一点:根据,创建非静态数据成员甚至不需要通过引用捕获,因此decltype
不可能引用这样的成员。我同意这一点,但是,为什么可选的lambda[](auto&v)->decltype(auto){return v;}
为所有尝试的编译器返回左值引用?@rollbear,因为它作用于声明的v
类型,而不是声明的u
类型v
被声明为引用类型,u
不是。我所追求的行为仅仅是理解,因为我需要记录它。嘿,哇。我们刚刚讨论了通过复制捕获引用是捕获引用还是捕获副本。。。这一切都是因为诊断是decltype()
等。-这不是odr使用,返回的是外部对象的类型-不是相同名称的副本。改变捕获名单中的名字暗示了一个令人惊讶的事实。。。然后我举世闻名的谷歌搜索能力把我带到了你们举世闻名的回答能力
auto i = [&]() -> decltype(auto) { return (u); };