#include <type_traits>
#include <utility>
int main()
{
auto f1 = [](auto&& e) -> auto
{
return e;
};
auto f2 = [](auto&& e) -> auto&
{
return e;
};
auto f3 = [](auto&& e) -> auto&&
{
return e;
};
auto f4 = [](auto&& e) -> decltype(auto)
{
return e;
};
int n{};
f1(std::move(n)); // ok
f2(std::move(n)); // ok
f3(std::move(n)); // ok
f4(std::move(n)); // error
}
clang 的错误消息:
error : rvalue reference to type 'int' cannot bind to lvalue of type 'int'
对我来说,decltype(auto)
只有三种可能的推导类型:
自动
自动&
自动&&
为什么f4
错误,而其他三个都正常?
最佳答案
这是一个 GCC bug 。
decltype(auto) = e
等价于 decltype(e)
并产生 e
的声明类型。
auto
用作模板参数,这意味着 auto&&
与发明的模板参数的 T&&
(转发引用)相同。
对于f1,返回类型被推导为int
。
对于f2,返回类型auto&
相当于T&
,并推导出T=int
,它是类型左值 e
,此处将 int&
绑定(bind)到 e
。
对于f3请考虑:
auto&& t = n;
static_assert(std::is_same_v<decltype(t), int&>); // true
对于f3
的返回,auto&&
相当于发明的模板参数T&&
,它是一个转发引用,它用一个左值,产生 T&
并推导出 T=int
,然后再次...将 int&
绑定(bind)到左值 e
。
现在对于 f4 考虑一下:
int&& r = 9;
static_assert(std::is_same_v<decltype(r), int&&>); // true (1)
decltype(auto) t = r; // fail with the same error you got.
f4
的参数也是一个转发引用T&&
,用xvalue std::move(n)
初始化,由此推导出T=int
产生参数 int&& e
。返回类型为 decltype(auto)
和 return e
意味着实际返回是 decltype(e)
,那么如您所见 (1 ) 为 true,对于 decltype(e)
也是如此,这意味着 f4
的实际返回是 int&&
...并且有问题,f4
正在尝试将右值 int&&
绑定(bind)到左值 e
,这是禁止的。
您还可以查看@StoryTeller's answer针对 GCC 错误。
关于c++ - 为什么 decltype(auto) 不能按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53717911/