C++ 14以降では、汎用ラムダを使用できます。
auto generic_lambda = [] (auto param) {};
これは基本的に、その呼び出し演算子がautoとしてマークされたパラメーターに基づいてテンプレート化されることを意味します。
問題は、可変個の関数テンプレートがどのように機能するかと同様に、可変個のパラメーターを受け入れることができるラムダを作成する方法です。これが不可能な場合、同じ方法で使用できる最も近いものは何ですか?どのように保管しますか? std::function
?
可変長の汎用ラムダをどのように作成しますか?
次の構文を使用して、可変個の汎用ラムダを作成できます。
auto variadic_generic_lambda = [] (auto... param) {};
基本的には、auto
(おそらく修飾されたref)とパラメーターパック名の間に...
を追加するだけです。
したがって、通常、ユニバーサル参照を使用すると次のようになります。
auto variadic_generic_lambda = [] (auto&&... param) {};
パラメータの使用方法は?
そのため、可変引数ジェネリックパラメーターはテンプレートパラメーターパックタイプを持つと見なす必要があります。これは多かれ少なかれ、それらのパラメーターのすべての使用ではないにしてもほとんどの場合、テンプレートを何らかの方法で必要とすることを意味しています。
典型的な例を次に示します。
#include <iostream>
void print(void)
{
}
template <typename First, typename ...Rest>
void print(const First& first, Rest&&... Args)
{
std::cout << first << std::endl;
print(Args...);
}
int main(void)
{
auto variadic_generic_lambda = [] (auto... param)
{
print(param...);
};
variadic_generic_lambda(42, "lol", 4.3);
}
可変長の汎用ラムダをどのように保存しますか?
auto
を使用して独自の型の変数にラムダを格納するか、または std::function
に格納できますが、呼び出すことしかできません。そのstd::function
に与えた固定署名を使用して:
auto variadic_generic_lambda = [] (auto... param) {};
std::function<void(int, int)> func = variadic_generic_lambda;
func(42, 42); // Compiles
func("lol"); // Doesn't compile
可変個の汎用ラムダのコレクションはどうですか?
すべてのラムダは異なる型を持っているため、直接型をSTLの通常の同種のコンテナに格納することはできません。非ジェネリックラムダで行われる方法は、対応するstd::function
に保存することです。これは、固定のシグネチャ呼び出しを持ち、ラムダはそもそもジェネリックではなく、呼び出すことしかできないため、何も制限しません。そのように:
auto non_generic_lambda_1 = [] (int, char) {};
auto non_generic_lambda_2 = [] (int, char) {};
std::vector<std::function<void(int, char)>> vec;
vec.Push_back(non_generic_lambda_1);
vec.Push_back(non_generic_lambda_2);
このstorageセクションの最初の部分で説明したように、特定の固定呼び出しシグネチャに制限できる場合は、可変長の汎用ラムダでも同じことができます。
できない場合は、次のような何らかの異種コンテナが必要になります。
std::vector<boost::variant>
std::vector<boost::any>
boost::fusion::vector
異種コンテナの例については、 この質問 を参照してください。
ラムダに関するより一般的な情報、生成されるメンバーの詳細、およびラムダ内でのパラメーターの使用方法については、以下を参照してください。
あなたの意図がわからないが、代わりにstd::function
ラムダ自体を使用して、パラメータをキャプチャできます。これは、ブーストメーリングリストで説明されている例です。 boost :: hana 実装で使用されます
auto list = [](auto ...xs) {
return [=](auto access) { return access(xs...); };
};
auto head = [](auto xs) {
return xs([](auto first, auto ...rest) { return first; });
};
auto tail = [](auto xs) {
return xs([](auto first, auto ...rest) { return list(rest...); });
};
auto length = [](auto xs) {
return xs([](auto ...z) { return sizeof...(z); });
};
// etc...
// then use it like
auto three = length(list(1, '2', "3"));
このことを考慮
#include <iostream>
namespace {
auto out_ = [] ( const auto & val_)
{
std::cout << val_;
return out_ ;
};
auto print = [](auto first_param, auto... params)
{
out_(first_param);
// if there are more params
if constexpr (sizeof...(params) > 0) {
// recurse
print(params...);
}
return print;
};
}
int main()
{
print("Hello ")("from ")("GCC ")(__VERSION__)(" !");
}
( wandbox here )この「印刷」ラムダは次のとおりです。
また、テンプレートが見えません。 (すぐ下:))ラジオノイズのように見えるC++コードはありません。シンプルでクリーン、そして最も重要なこと:
「新しい言語のように感じる」のも不思議ではありません。