Рассматривать:
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), что, конечно, мне понятно. Мы не можем привязать константную ссылку к rvalue ссылке. Хорошо.
Может ли кто-нибудь объяснить мне, что на самом деле lambda4
«s p
параметр? Здесь (Y) компилятор действительно компилирует его, хотя я передаю ему аргумент const reference.
В чем разница между lambda2
а также lambda4
типы в смысле вывода типа?
auto lambda2 = [] (std::vector<int>&&) {};
Это примерно эквивалентно:
struct __lambda2 {
void operator()(std::vector<int>&& ) {}
} lambda2;
Здесь оператор вызова принимает ссылку на rvalue — он принимает только значения rvalue. c_data()
дает вам lvalue, отсюда и ошибка компилятора.
С другой стороны,
auto lambda4 = [] (auto&& p) {};
примерно эквивалентно:
struct __lambda4 {
template <class T>
void operator()(T&& ) {}
} lambda4;
T&&
, где T
является параметром шаблона, а не является ссылкой на выводимое значение (хотя это и выглядит так) — это пересылка ссылка. Он может принимать как lvalues, так и rvalues - и выведет T
по-разному в зависимости от двух категорий стоимости (T=std::vector<int>
в первом звонке и T=std::vector<int> const&
во-вторых). Так как это принимает lvalues, ошибки компиляции нет.
Обратите внимание, что ссылки на пересылку имеют только форму 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
};
Других решений пока нет …