[英]auto&& return type from a C++ lambda
我有兴趣了解尾随auto&&
返回类型的确切含义,特别是与decltype(auto)
的区别,后者在这里不起作用,以及未指定的返回类型,后者也不起作用。
在下面的代码中, fn
返回参数的x_
字段。 当参数是左值时, x_
作为左值返回,等等。
在fn_bad[123]
的示例中,它似乎返回int
,即使提供了左值参数也是如此。 我明白为什么-> auto
会导致这种情况,但我希望-> decltype(auto)
返回int&
。 为什么只能-> auto&&
工作?
#include <utility>
struct Foo { int x_; };
int main() {
auto fn_bad1 = [](auto&& foo) -> decltype(auto) { return std::forward<decltype(foo)>(foo).x_; };
auto fn_bad2 = [](auto&& foo) -> auto { return std::forward<decltype(foo)>(foo).x_; };
auto fn_bad3 = [](auto&& foo) { return std::forward<decltype(foo)>(foo).x_; };
auto fn = [](auto&& foo) -> auto&& { return std::forward<decltype(foo)>(foo).x_; };
Foo a{};
fn(a) = fn(Foo{100}); // doesn't compile with bad1, bad2, bad3
}
但我希望 ->
decltype(auto)
返回int&
这是decltype
的预期行为,
(强调我的)
检查实体的声明类型或表达式的类型和值类别。
1) 如果参数是未加括号的 id-expression 或未加括号的class 成员访问表达式,则 decltype 产生此表达式命名的实体的类型。
因此std::forward<decltype(foo)>(foo).x_
上decltype(auto)
的结果产生数据成员x_
的类型,即int
。
如果您将括号添加为
[](auto&& foo) -> decltype(auto) { return (std::forward<decltype(foo)>(foo).x_); };
// ^ ^
然后
2) 如果参数是
T
类型的任何其他表达式,并且a) 如果表达式的值类别是 xvalue,则
decltype
产生T&&
;
b) 如果表达式的值类别是左值,则decltype
产生T&
;
c) 如果表达式的值类别是纯右值,则decltype
产生T
请注意,如果 object 的名称被括号括起来,它会被视为普通的左值表达式,因此
decltype(x)
和decltype((x))
通常是不同的类型。
然后,正如您所说,当将左值传递给 lambda 时,表达式(std::forward<decltype(foo)>(foo).x_)
是左值,则返回类型将为int&
; 当传递一个右值时,表达式是一个 xvalue,然后返回类型将是int&&
(这可能会导致悬空引用问题)。
对于第二种情况,根据模板参数推导的正常规则,无论何时传递左值或右值,返回类型始终为int
。
第三种情况与第二种情况相同。
对于第 4 种情况,应用转发引用的特殊规则,则当返回表达式为左值时返回类型为int&
,当返回表达式为右值时返回类型为int&&
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.