web-dev-qa-db-ja.com

C ++ 14にすでに汎用ラムダがある場合に、C ++ 20に導入されたテンプレートラムダの必要性は何ですか?

c ++ 14 以下を書くことを可能にする一般的なラムダを導入しました:

auto func = [](auto a, auto b){
    return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

このジェネリックラムダfuncは、テンプレート関数funcが機能するのと同じように機能することは明らかです。

C++委員会が汎用ラムダのテンプレート構文を追加することにしたのはなぜですか?

95
coder3101

C++ 14ジェネリックラムダは、次のようなoperator ()でファンクタを生成する非常に優れた方法です。

template <class T, class U>
auto operator()(T t, U u) const;

しかし、これは好きではありません:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

これも好きではありません:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

これも好きではありません(ただし、実際に使用するには少し注意が必要です)。

template <class T>
auto operator()() const; // No deduction

C++ 14ラムダは問題ありませんが、C++ 20を使用すると、これらのケースを簡単に実装できます。

108
Quentin

C++ 20ではテンプレート化されたラムダを使用できるため、SFINAE式よりも簡単な方法で型を制限できます。

auto lambda = []<typename T>(std::vector<T> t){};

このラムダはベクタータイプでのみ機能します。

30
Antoine Morrier

C++ 20に受け入れられた proposal には、モチベーションセクションが長く、例が示されています。それの前提はこれです:

ジェネリックラムダを定義するための現在の構文が作成者によって不十分であると見なされる理由はいくつかあります。その要点は、通常の関数テンプレートで簡単に実行できるいくつかのことは、汎用ラムダで実行するにはかなりのフープジャンプを必要とするか、まったく実行できないということです。通常の関数テンプレートと同様に。

以下はかなりの数の例です。

C++ 20で導入されたラムダの新しい「使い慣れたテンプレート構文」により、_for_types_や_for_range_などの構成が実行可能になり、C++ 17の代替と比較して読みやすくなります。

(ソース: C++ 20ラムダを使用したコンパイル時の反復

C++ 14とC++ 17の両方の汎用ラムダで実行できるもう1つの興味深いことは、テンプレートパラメータを明示的に渡すことによってoperator()を直接呼び出すことです。

C++ 14:

_   auto l = [](auto){ };
   l.template operator()<int>(0);
_

C++ 20:

_  auto l = []<typename T>(){ };
  l.template operator()<int>();
_

上記のC++ 14の例はまったく役に立ちません。引数に名前を付けてdecltypeを使用しないと、ラムダの本体でoperator()に提供されている型を参照する方法はありません。さらに、引数が必要ない場合でも、引数を渡す必要があります。

C++ 20の例は、ラムダの本文でTに簡単にアクセスできることと、nullaryラムダを任意にテンプレート化できることを示しています。これは、前述のコンパイル時構成の実装に非常に役立ちます。

19
Hamza.S