web-dev-qa-db-ja.com

ラムダ式を返す関数

C++ 11でラムダ関数を返す関数を書くことは可能だろうか。もちろん、1つの問題は、そのような関数を宣言する方法です。各ラムダには型がありますが、その型はC++では表現できません。私はこれがうまくいくとは思わない:

auto retFun() -> decltype ([](int x) -> int)
{
    return [](int x) { return x; }
}

これも:

int(int) retFun();

私は、ラムダから関数へのポインタなどへの自動変換を認識していません。関数オブジェクトを手作りしてそれを返す唯一のソリューションですか?

83

ラムダ関数が変換可能なstd::functionを使用するだけで、手作りの関数オブジェクトは必要ありません。

次の例では、整数恒等関数を返します。

std::function<int (int)> retFun() {
    return [](int x) { return x; };
}
93
Sean

この単純な例では、_std::function_は必要ありません。

標準§5.1.2/ 6より:

lambda-expressionlambda-captureなしのクロージャー型には、同じパラメーターと戻り値の型を持つ関数へのポインターへのパブリック非仮想非明示const変換関数がありますクロージャー型の関数呼び出し演算子として。この変換関数によって返される値は、呼び出されたときに、クロージャータイプの関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。

関数にはキャプチャがないため、ラムダをint (*)(int)型の関数へのポインターに変換できます。

_typedef int (*identity_t)(int); // works with gcc
identity_t retFun() { 
  return [](int x) { return x; };
}
_

それが私の理解です。間違っている場合は修正してください。

29
user534498

ラムダ関数の戻り値の型を明示的に指定するべきではないため、他のラムダ関数からラムダ関数を返すことができます。グローバルスコープでそのようなものを書くだけです:

 auto retFun = []() {
     return [](int x) {return x;};
 };
20
dzhioev

この質問はC++ 11について具体的に尋ねていますが、これにつまずいてC++ 14コンパイラにアクセスできる他の人のために、C++ 14は通常の関数の推定戻り型を許可します。したがって、質問の例は、単に-> decltype...関数パラメーターリストの後の句:

auto retFun()
{
    return [](int x) { return x; }
}

ただし、複数のreturn <lambda>;が関数に表示されます。これは、戻り型の推論の制限により、すべてのreturnステートメントが同じ型の式を返す必要があるが、すべてのラムダオブジェクトにはコンパイラによって独自の一意の型が与えられるため、return <lambda>;式はそれぞれ異なる型を持ちます。

15
Anthony Hall

次のように書く必要があります。

auto returnFunction = [](int x){
    return [&x](){
        return x;
    }();
};

関数としてリターンを取得し、次のように使用します。

int val = returnFunction(someNumber);
0
Terens Tare