c++ - 为什么 decltype(auto) 不能按预期工作?

标签 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
}

clang 的错误消息:

error : rvalue reference to type 'int' cannot bind to lvalue of type 'int'

对我来说,decltype(auto) 只有三种可能的推导类型:

  1. 自动
  2. 自动&
  3. 自动&&

为什么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/

相关文章:

C++ 返回在堆上创建的对象并修改它,不改变它吗?

带有 Function.apply 的 Java 泛型

c++ - 如何返回 constexpr 的元组

c++ - 在 OpenCV 中,有没有比 cv::merge 和 cv::split 更有效地组合/分离图像 channel 的方法?

c++ - C++ 中 protobuf 消息的长度前缀

时间:2019-03-17 标签:c#DynamicWhereclauseinalambda

python - Keras Lambda层没有输出张量形状,编译模型时出错

c++ - 在编译时截断字符串

c++ - 如何强制 Mac 窗口到前台?

python - 如何在不同的平台/技术中使用经过训练的神经网络?