GCC allows the following syntax as an extension:
// a functional object that will add two like-type objects
auto add = [] <typename T> (T a, T b) { return a + b; };
In n3418, the 2012 proposal for generic lambdas, we see syntax that allows the above:
overload( []<class T>(T* p) {...},
However, since it is an extension the syntax is clearly absent (or not allowed.) In what situations would the above be useful when we have auto, and why is the syntax absent (or not allowed)?
It seems to me that C++14's polymorphic lambdas are just more terse.
You can reproduce the effect of your sample situation like the following:
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
}
Though there are many cases where the GCC extension is more capable, not only on your use case (where it fits more naturally). For example, regarding non-type template parameters:
#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
Complex generic parameter types:
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
I dunno the discussion involving inclusion of generic lambdas, but I can see one pondering whether such extension is worth including when the current syntax covers the majority of use cases, is terse, and appropriate for the intent of lambdas, which most often is for producing short snippets of code.
The GCC extension has been decided to become part of C++ on the first C++20 ISO standards meeting:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With