8

GCCでは、次の構文を拡張として使用できます。

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

汎用ラムダの 2012年提案であるn3418では、上記を可能にする構文が見られます。

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

ただし、これは拡張機能であるため、構文が明らかに存在しない (または許可されていない)。auto がある場合、上記はどのような状況で役立つでしょうか。また、構文が存在しない (または許可されていない) のはなぜですか?

4

1 に答える 1

10

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>{});    
}

コリル

複雑なジェネリック パラメーターの型:

void foo() {}

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

    accept_no_args_fun_only(foo);
}

コリル

変数:

#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});
}

コリル

一般的なラムダを含めることに関する議論はわかりませんが、現在の構文がほとんどのユースケースをカバーし、簡潔で、ラムダの目的に適している場合、そのような拡張を含める価値があるかどうかを熟考している人を見ることができます。コードの短いスニペット。

編集

GCC 拡張機能は、最初の C++20 ISO 標準会議で C++ の一部になることが決定されました。

于 2014-10-19T20:05:13.003 に答える