【问题标题】:Generic lambda, type deduction of actual parameter (auto)泛型lambda,实参类型推导(auto)
【发布时间】:2016-03-17 16:16:41
【问题描述】:

考虑:

struct Foo {
    std::vector<int> data () const { return vec; }
    const std::vector<int>& c_data () const { return vec; }

    std::vector<int> vec {};
};

auto lambda1 = [] (const std::vector<int>&) {};
auto lambda2 = [] (std::vector<int>&&) {};

auto lambda3 = [] (const auto&) {};
auto lambda4 = [] (auto&& p) {};

而用法是:

Foo f {};

lambda1 (f.data ());
lambda1 (f.c_data ());

lambda2 (f.data ());
lambda2 (f.c_data ()); // (X)

lambda3 (f.data ());
lambda3 (f.c_data ());

lambda4 (f.data ());
lambda4 (f.c_data ()); // (Y)

这段代码因为 (X) 导致编译失败,这当然是我可以理解的。我们不能将 const 引用绑定到右值引用。很好。

谁能解释一下lambda4p 参数的实际类型是什么?这里 (Y),即使我将 const 引用参数传递给它,编译器也会编译它。

lambda2lambda4 类型在类型推导意义上的区别是什么?

【问题讨论】:

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


【解决方案1】:
auto lambda2 = [] (std::vector<int>&&) {};

这大致相当于:

struct __lambda2 {
    void operator()(std::vector<int>&& ) {}
} lambda2;

这里的调用操作符接受一个右值引用——它只接受右值。 c_data() 给你一个左值,因此编译器错误。

另一方面,

auto lambda4 = [] (auto&& p) {};

大致相当于:

struct __lambda4 {
    template <class T>
    void operator()(T&& ) {}
} lambda4;

T&amp;&amp;,其中T 是一个模板参数,它不是对推导类型的右值引用(即使它看起来像这样)——它是一个转发 引用。它可以同时接受左值和右值——并且会根据两个值类别(第一次调用中的T=std::vector&lt;int&gt; 和第二次调用中的T=std::vector&lt;int&gt; const&amp;)以不同的方式推导出 T。由于它接受左值,因此没有编译错误。

请注意,转发引用只有T&amp;&amp;(用于模板参数T)和auto&amp;&amp; 的形式。例如:

template <class U>
struct X {
    template <class T> void foo(T&& );      // forwarding reference
    template <class T> void bar(T const&&); // rvalue reference to const T
    void quux(U&& );                        // rvalue reference to U
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-19
    • 1970-01-01
    相关资源
    最近更新 更多