为什么decltype(auto)无法按预期工作?

时间:2018-12-11 05:30:06

标签: c++ lambda c++14 decltype type-deduction

#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)只有三种可能的推导类型:

  1. auto
  2. auto&
  3. auto&&

为什么在其他所有三个都正常的情况下出现f4错误?

1 个答案:

答案 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错误。