Какая польза от лямбда-трейлинга с возвращаемым типом auto? - PullRequest
0 голосов
/ 29 августа 2018

Какая польза от добавления -> auto в []() -> auto { return 4; }?

Для меня - ничем не отличается от []() { return 4; }

1 Ответ

0 голосов
/ 29 августа 2018

Это auto по умолчанию. Стандарт, [expr.prim.lambda] / 4 , гласит:

Если лямбда-выражение не включает лямбда-декларатор , это как если бы лямбда-декларатор был (). Тип лямбда-возврата - auto, который заменяется типом конечного возврата , если он предоставлен и / или выведен из операторов return, как описано в [dcl.spec.auto].

Мое добавление.

Итак, -> auto само по себе бесполезно. Однако мы можем сформировать другие типы возврата с auto, а именно: -> auto&, -> const auto&, -> auto&&, -> decltype(auto). Применяются стандартные правила вычета типа возврата. Следует иметь в виду, что auto никогда не выводится как ссылочный тип, поэтому по умолчанию лямбда возвращает не ссылочный тип.

Несколько (тривиальных) примеров:

// 1.
int foo(int);
int& foo(char);

int x;

auto lambda1 = [](auto& x) { return x; };
static_assert(std::is_same_v<decltype(lambda1(x)), int>);

auto lambda2 = [](auto& x) -> auto& { return x; };
static_assert(std::is_same_v<decltype(lambda2(x)), int&>);

// 2.
auto lambda3 = [](auto x) { return foo(x); };
static_assert(std::is_same_v<decltype(lambda3(1)), int>);
static_assert(std::is_same_v<decltype(lambda3('a')), int>);

auto lambda4 = [](auto x) -> decltype(auto) { return foo(x); };
static_assert(std::is_same_v<decltype(lambda4(1)), int>);
static_assert(std::is_same_v<decltype(lambda4('a')), int&>);

// 3.
auto lambda5 = [](auto&& x) -> auto&& { return std::forward<decltype(x)>(x); };
static_assert(std::is_same_v<decltype(lambda5(x)), int&>);
static_assert(std::is_same_v<decltype(lambda5(foo(1))), int&&>);
static_assert(std::is_same_v<decltype(lambda5(foo('a'))), int&>);

Добавление PiotrNycz. Как указано в комментариях (благодарность @StoryTeller) - реальное использование - это версия с auto& и const auto& и "Вырожденный случай просто не стоит отклонять назад запретить. "

См:

int p = 7;
auto p_cr = [&]()  -> const auto& { return p; };
auto p_r = [&]()  -> auto& { return p; };
auto p_v = [&]()  { return p; }; 

const auto& p_cr1 = p_v(); // const ref to copy of p
const auto& p_cr2 = p_cr(); // const ref to p
p_r() = 9; // we change p here

std::cout << p_cr1 << "!=" << p_cr2 << "!\n";
// print 7 != 9 !
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...