泛型lambda,实参的类型推导(auto)
Generic lambda, type deduction of actual parameter (auto)
考虑:
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 引用绑定到右值引用。很好。
谁能给我解释一下 lambda4
的 p
参数的实际类型是什么?这里 (Y),即使我向它传递 const 引用参数,编译器也会编译它。
lambda2
和 lambda4
类型在类型推导意义上有什么区别?
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&&
,其中 T
是一个模板参数,不是对推导类型的右值引用(即使它看起来像这样)——它是一个 转发参考。它可以接受左值和右值 - 并且会根据两个值类别(第一次调用中的 T=std::vector<int>
和第二次调用中的 T=std::vector<int> const&
)以不同方式推断 T
。因为它接受左值,所以没有编译错误。
请注意,转发引用只有 T&&
(模板参数 T
)和 auto&&
形式。例如:
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
};
考虑:
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 引用绑定到右值引用。很好。
谁能给我解释一下 lambda4
的 p
参数的实际类型是什么?这里 (Y),即使我向它传递 const 引用参数,编译器也会编译它。
lambda2
和 lambda4
类型在类型推导意义上有什么区别?
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&&
,其中 T
是一个模板参数,不是对推导类型的右值引用(即使它看起来像这样)——它是一个 转发参考。它可以接受左值和右值 - 并且会根据两个值类别(第一次调用中的 T=std::vector<int>
和第二次调用中的 T=std::vector<int> const&
)以不同方式推断 T
。因为它接受左值,所以没有编译错误。
请注意,转发引用只有 T&&
(模板参数 T
)和 auto&&
形式。例如:
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
};