我有兴趣了解尾随auto&&返回类型的确切含义,特别是区别于这里不工作的decltype(auto),以及未指定的返回类型,后者也不起作用。
在下面的代码中,fn返回参数的x_字段。当参数是lvalue时,x_返回为lvalue,等等。
在fn_bad[123]的示例中,它似乎返回int,即使提供了lvalue参数。我明白为什么-> 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
}发布于 2020-05-12 01:19:33
但我预计->
decltype(auto)会返回int&
这是decltype的预期行为,
(强调地雷)
检查实体或的声明类型、表达式的类型和值类别。 1)如果参数是非括号的id-表达式或非括号的类成员访问表达式,则解密类型将产生由该表达式命名的实体的类型。
因此,decltype(auto)在std::forward<decltype(foo)>(foo).x_上的结果产生了数据成员x_的类型,即int。
如果将括号添加为
[](auto&& foo) -> decltype(auto) { return (std::forward<decltype(foo)>(foo).x_); };
// ^ ^然后
2)如果参数是
T类型的任何其他表达式,如果表达式的值类别为xvalue,则decltype生成T&&; b)如果表达式的值范畴为lvalue,则decltype生成T&; c)如果表达式的值类别为prvalue,则decltype生成T。 注意,如果对象的名称为括号,则将其视为一个普通的lvalue表达式,因此decltype(x)和decltype((x))通常是不同的类型。
然后,正如您所说的,当将lvalue传递给lambda时,表达式(std::forward<decltype(foo)>(foo).x_)是lvalue,则返回类型为int&;当传递rvalue时,表达式为xvalue,则返回类型为int&& (这可能会导致悬空引用问题)。
对于第二种情况,根据模板参数推导的正常规则,每当传递lvalue或rvalue时,返回类型总是int。
第三例与第二例相同。
对于第四种情况,应用了转发参考的特殊规则,当返回表达式为lvalue时,返回类型为int&,当返回表达式为rvalue时,返回类型为int&&。
https://stackoverflow.com/questions/61742004
复制相似问题