Общая лямбда, тип вычета фактического параметра (авто)

Рассматривать:

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 типы в смысле вывода типа?

2

Решение

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
};
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]