#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
}
c语的错误消息:
错误:对“ int”类型的右值引用无法绑定到“ int”类型的左值
对我来说,decltype(auto)
只有三种可能的推导类型:
auto
auto&
auto&&
为什么在其他所有三个都正常的情况下出现f4
错误?
答案 0 :(得分:2)
这是GCC bug。
decltype(auto) = e
等效于decltype(e)
,并产生声明的类型e
。
auto
作为模板参数,这意味着auto&&
与发明模板参数的T&&
(转发参考)相同。
对于 f1 ,返回类型推导为int
。
对于 f2 ,返回类型auto&
等同于T&
,并推导T=int
,它是左值e
的类型,在这里,您将int&
绑定到e
。
对于 f3 ,请考虑以下事项:
auto&& t = n;
static_assert(std::is_same_v<decltype(t), int&>); // true
对于返回f3
的,auto&&
等同于发明的模板参数T&&
,它是一个转发引用,该模板参数用左值初始化,产生T&
推导T=int
,然后再次将int&
绑定到左值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
的参数也是用x值T&&
初始化的转发引用std::move(n)
,推论出T=int
产生了参数int&& e
。返回类型为decltype(auto)
和return e
表示实际收益为decltype(e)
,然后您可以看到(1)为true,decltype(e)
的保留时间相同,这意味着f4
的实际返回值为int&&
...并且存在问题,f4
试图将右值int&&
绑定到左值e
禁止。
您也可以查看@StoryTeller's answer中的GCC错误。