rol*_*ear 9 c++ lambda decltype c++11 c++14
我有编译器不同意一个小的C++ 14代码片段:
#include <cassert>
struct unmovable {
unmovable() {}
unmovable(unmovable&&) = delete;
};
int main()
{
unmovable u;
auto i = [&]() -> decltype(auto) { return u; };
auto& uu = i();
assert(&uu == &u);
}
Run Code Online (Sandbox Code Playgroud)
该程序被g ++ 4.9.3,g ++ - 5.1.0,g ++ - 5.2.0和VisualStudio 2015接受,但不是由clang ++ - 3.7接受.
clang ++ - 3.7推断返回类型为unmovable
(值)而不是unmovable&
.
如果程序稍微改变,以便变量u
是全局的,那么所有编译器都会同意错误.
据我了解,当变量是本地变量时,u
lambda中捕获的应该是类型unmovable&
.
我没有C++ 14标准,但希望github的草案是相关的.我的7.1.6.2和7.1.6.4的解释是,decltype(auto)
成为decltype(u)
从返回,这在全球的情况下应该是unmovable
(值),并在当地的拉姆达参考捕获u
,它应该成为unmovable&
自捕获的变量的类型必须为unmovable&
.这表明clang ++错了.
如果我稍微更改lambda及其使用:
auto i = [](auto& v) -> decltype(auto) { return v; };
auto& uu = i(u);
Run Code Online (Sandbox Code Playgroud)
然后所有编译器都接受它,无论u
是全局还是本地,我认为这加强了我对演绎的解释decltype(auto)
,因为v
这里肯定会变成类型unmovable&
.
我的解释是否正确,因此clang ++不正确?
小智 7
clang对我来说似乎是正确的.我同意你的解释,即在lambda返回类型必须是decltype(u)
,但不是说decltype(u)
是unmovable&
.
5.1.2 Lambda表达式[expr.prim.lambda]
18 lambda 表达式的复合语句中的每个id表达式都是由副本捕获的实体的odr-use(3.2)转换为对闭包类型的相应未命名数据成员的访问.[ 注意:不是odr-use 的id表达式是指原始实体,永远不是闭包类型的成员.此外,这样的id表达式不会导致实体的隐式捕获.- 尾注 ] [...]
19每次出现的
decltype((x))
地方[...]
p19不适用,因为你有decltype(u)
,不是decltype((u))
.
p18然后说,因为u
in decltype(u)
不是odr-use,它指的是原始实体,它不会转换为闭包类型成员的访问.
但是,p19确实表明如果你把你的return
陈述写成
auto i = [&]() -> decltype(auto) { return (u); };
Run Code Online (Sandbox Code Playgroud)
那么lambda将u
通过引用返回.这将适用于clang,如果这是你所追求的行为.
归档时间: |
|
查看次数: |
1351 次 |
最近记录: |