Using template parameter in a generic lambda

无人久伴 提交于 2019-12-01 02:09:40

问题


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)?


回答1:


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.

EDIT

The GCC extension has been decided to become part of C++ on the first C++20 ISO standards meeting:

  • http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0428r1.pdf


来源:https://stackoverflow.com/questions/26435052/using-template-parameter-in-a-generic-lambda

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!