auto
C ++ 14標準でジェネリックラムダはどのように機能しますか(引数の型としてのキーワード)?
それは、C ++テンプレートに基づいていますか?異なる引数型ごとに、コンパイラーは同じ本体を使用して新しい関数を生成しますが、型を置き換えます(コンパイル時のポリモーフィズム)、それともJavaのジェネリック(型消去)に似ていますか?
コード例:
auto glambda = [](auto a) { return a; };
auto
C ++ 14標準でジェネリックラムダはどのように機能しますか(引数の型としてのキーワード)?
それは、C ++テンプレートに基づいていますか?異なる引数型ごとに、コンパイラーは同じ本体を使用して新しい関数を生成しますが、型を置き換えます(コンパイル時のポリモーフィズム)、それともJavaのジェネリック(型消去)に似ていますか?
コード例:
auto glambda = [](auto a) { return a; };
回答:
ジェネリックラムダはで導入されましたC++14
。
簡単に言うと、ラムダ式で定義されたクロージャタイプには、のラムダの通常の非テンプレート呼び出し演算子ではなく、テンプレート化された呼び出し演算子がありC++11
ます(もちろん、auto
パラメータリストに少なくとも1回出現する場合)。
だからあなたの例:
auto glambda = [] (auto a) { return a; };
glambda
このタイプのインスタンスを作成します:
class /* unnamed */
{
public:
template<typename T>
T operator () (T a) const { return a; }
};
C ++ 14標準ドラフトn3690の5.1.2 / 5項では、特定のラムダ式のクロージャタイプの呼び出し演算子を定義する方法を指定しています。
非ジェネリックなラムダ式のクロージャタイプには、パブリックインライン関数呼び出し演算子(13.5.4)があり、そのパラメータと戻り値のタイプは、ラムダ式のパラメータ宣言節とトレーリングリターンタイプによってそれぞれ記述されます。ジェネリックラムダの場合、クロージャタイプにはパブリックインライン関数呼び出し演算子メンバーテンプレート(14.5.2)があり、そのtemplate-parameter-listは、ラムダのparameter-declaration-clauseでautoが出現するたびに1つの発明された型template-parameterで構成されます。出現順に。発明された型template-parameterは、対応するパラメーター宣言が関数パラメーターパック(8.3.5)を宣言する場合のパラメーターパックです。関数呼び出し演算子テンプレートの戻り値の型と関数パラメーターは、ラムダ式の後続戻り型とパラメーター宣言句から、parameter-declaration-clauseのdecl-specifiers内の各autoを、対応する発明されたテンプレートパラメータ。
最後に:
さまざまな引数の型ごとに、コンパイラーは同じ本体で型が変更された関数を生成するテンプレートに似ていますか、それともJavaのジェネリックに似ていますか?
上記の段落で説明したように、ジェネリックラムダは、テンプレート化された呼び出し演算子を持つ一意で名前のないファンクターの構文糖衣にすぎません。それはあなたの質問に答えるはずです:)
int main () { struct X {}; std::vector<X> x; }
)
残念ながら、それらはC ++ 11の一部ではありません(http://ideone.com/NsqYuq):
auto glambda = [](auto a) { return a; };
int main() {}
g ++ 4.7の場合:
prog.cpp:1:24: error: parameter declared ‘auto’
...
ただし、ポートランドの一般的なラムダの提案に従って、C ++ 14で実装する方法は次のとおりです。
[](const& x, & y){ return x + y; }
これにより、ほとんどの場合、通常は匿名ファンクタークラスが作成されますが、型がないため、コンパイラーはテンプレート化されたメンバーを生成しoperator()
ます。
struct anonymous
{
template <typename T, typename U>
auto operator()(T const& x, U& y) const -> decltype(x+y)
{ return x + y; }
};
または、新しい(一般的な(多形)ラムダ式の提案)の提案に従って
auto L = [](const auto& x, auto& y){ return x + y; };
--->
struct /* anonymous */
{
template <typename T, typename U>
auto operator()(const T& x, U& y) const // N3386 Return type deduction
{ return x + y; }
} L;
したがって、はい、パラメータのすべての順列に対して、新しいインスタンス化が発生しますが、そのファンクタのメンバーは共有されます(つまり、キャプチャされた引数)。
-std=c++1y
ます。
auto
は従来の自動車と同じ控除規則を持っていますか?テンプレート化されたアナロジーに言及する場合、それは自動が自動ではないことを意味します。これはテンプレートタイプの控除と同じルールです。次に問題は:テンプレートの控除はと同等auto
ですか?
static
か、register
使用して、はい、とにかく:) auto
ボンネットの下に、通常のテンプレートが生成されていることが意味を。実際、ラムダはコンパイラ内部でファンクタクラスに置き換えられ、auto
パラメータはそれtemplate <T> ... (T ...)
が発行されることを意味します。
これは、C ++ 14に提案された機能(C ++ 11にはない)であり、テンプレートに似ています(または同等でさえあります)。たとえば、N3559は次の例を提供します。
たとえば、次の一般的なラムダ式を含むステートメント:
auto L = [](const auto& x, auto& y){ return x + y; };
その結果、クロージャタイプが作成され、オブジェクトは以下の構造体と同様に動作します。
struct /* anonymous */ { template <typename T, typename U> auto operator()(const T& x, U& y) const // N3386 Return type deduction { return x + y; } } L;