Использование параметра шаблона в общей лямбде

НКУ допускает следующий синтаксис в качестве расширения:

// a functional object that will add two like-type objects
auto add = [] <typename T> (T a, T b) { return a + b; };

В n3418, В предложении 2012 года об общих лямбдах мы видим синтаксис, позволяющий:

overload( []<class T>(T* p) {...},

Однако, поскольку это расширение, синтаксис явно отсутствует (или не разрешен). В каких ситуациях вышеприведенное будет полезно, когда у нас есть auto, и почему синтаксис отсутствует (или не разрешен)?

6

Решение

Мне кажется, что полиморфные лямбды в C ++ 14 более лаконичны.

Вы можете воспроизвести эффект вашей типовой ситуации следующим образом:

struct A {};
struct B {};

int operator+(A, A) { return 1; }
int operator+(B, B) { return 2; }
int operator+(A, B) { return 3; }
int operator+(B, A) { return 4; }

int main() {
auto add = [](auto a, decltype(a) b) { return a + b; };
auto flexible_add = [](auto a, auto b) { return a + b; };

add(A{}, A{});  // works
add(B{}, B{});  // works
add(A{}, B{});  // doesn't work

flexible_add(A{}, A{});  // works
flexible_add(B{}, B{});  // works
flexible_add(A{}, B{});  // works

auto deref = [](auto *a) { return *a; };
int foo{};
A a;
B b;
deref(&foo); // works
deref(&a);   // works
deref(&b);   // works
deref(foo);  // doesn't work
deref(a);    // doesn't work
deref(b);    // doesn't work
}

Хотя есть много случаев, когда расширение GCC более функционально, не только в вашем случае использования (где оно подходит более естественно). Например, относительно параметров шаблона нетипичного типа:

#include <cstddef>
#include <utility>
#include <iostream>

void print(std::initializer_list<std::size_t> il)
{
for (auto&& elem : il) std::cout << elem << std::endl;
}

int main()
{
auto indexed_lambda = [] <std::size_t... Is> (std::index_sequence<Is...>) { print({Is...}); };

indexed_lambda(std::make_index_sequence<5>{});
}

Coliru

Сложные универсальные типы параметров:

void foo() {}

int main() {
auto accept_no_args_fun_only = [] <typename R> (R (*)()) {};

accept_no_args_fun_only(foo);
}

Coliru

Variadics:

#include <tuple>
#include <vector>

int main() {
auto accept_vector = [] (std::vector<auto> &&) {}; // Unconstrained placeholder from Concept TS, but not variadic
auto accept_tuple = [] <typename... Args> (std::tuple<Args...> &&) {};

accept_vector(std::vector{42});
accept_tuple(std::tuple{42});
}

Coliru

Я не знаю дискуссию о включении общих лямбда-выражений, но я могу видеть одно размышление о том, стоит ли включать такое расширение, когда текущий синтаксис покрывает большинство вариантов использования, кратко и соответствует назначению лямбда-выражений, которое чаще всего предназначено для создания короткие фрагменты кода.

РЕДАКТИРОВАТЬ

Расширение GCC было решено стать частью C ++ на первая встреча стандартов C ++ 20 ISO:

8

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