2011-01-18 13 views
61

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

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

もこの:

int(int) retFun(); 

私はラムダから関数へのポインタ、たとえばへの自動変換、またはそのようないくつかを認識していませんよ。関数オブジェクトを手作りして返す唯一のソリューションですか?あなたはどのラムダ関数が変換されているし、ちょうどstd::functionを使用し、手作りの関数オブジェクトを必要としない

+0

すでに言われていることを追加するために、ステートレスラムダ関数は関数ポインタに変換可能です。 –

+2

IMO最初のオプションは 'decltype'のラムダが関数本体と同じでなく、したがって異なる型を持っています(return文を含めても) – Motti

+1

ちなみに、ラムダキャプチャ句が空の場合、暗黙的に関数へのポインタに変換できます。 – GManNickG

答えて

70

:この単純な例

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

Duh!私はStackOverflowが大好きです。トピックを研究してからStackOverflowで答えを得るまでにはずっと時間がかかりました。ありがとうSean! –

+3

これは 'std :: function'のコンストラクタでメモリの割り当てを引き起こします。 –

+2

@ Maxim Yegorushkin std :: functionには移動セマンティクスがあり、カスタムアロケータを使用することもできますし、C++ 0x作業草案には次のような注意事項があります: "[注意:実装は小さな呼び出し可能オブジェクトのために動的に割り当てられたメモリを避けてください。例では、fのターゲットは、オブジェクトやメンバ関数ポインタへのポインタや参照のみを保持するオブジェクトです。 " - end note" "基本的に、特定の実装がどのような割り当て戦略を使用しているかについて多くの仮定をすることはできませんが、とにかく独自の(プールされた)アロケータを使用することができます。 –

27

、あなたはstd::functionは必要ありません。標準5.1.2/6から

ないラムダキャプチャとラムダ式ための閉鎖型ポインタに公共非仮想非明示的なconstの変換機能を有していますクロージャ型の関数呼び出し演算子と同じパラメータと戻り値の型を持つように機能します。この変換関数によって返される値は、呼び出されるとクロージャ型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスとする。

あなたの関数は、キャプチャを持っていないので、それはラムダタイプint (*)(int)の関数へのポインタに変換できることを意味します

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

私の理解です。つまり、私はなら、私を修正違う。

+1

これは正しいと思います。残念ながら、私は使用している現在のコンパイラでは動作しません:VS 2010. std ::関数の変換は動作します。 –

+3

はい、この規則の最終的な文言はVC2010にとっては遅すぎました。 –

+0

コード例を追加しました。ここには[フルプログラム](https://gist.github.com/1342212)があります。 – jfs

12

ラムダ関数の戻り型を明示的に指定しないでください。他のラムダ関数からラムダ関数を返すことができます。

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

外側のラムダが単にreturn文で構成されている場合にのみ当てはまります。それ以外の場合は、戻り値の型を指定する必要があります。 –

+1

これは、std :: functionのランタイムポリモーフィズムを必要とせず、ラムダが空でないキャプチャリストを持つことを可能にするので、これは最良の答えですが、** const ** auto fun = ...を使用します。 –

10

質問は、特にこの時につまずくとC++ 14コンパイラ、Cへのアクセス権を持って他人のために、約C++ 11を尋ねるものの++:ちょうどグローバルスコープでそのような何かを書きます14では、通常の関数に対して推定された戻り値の型を使用できるようになりました。これは、複数のreturn <lambda>;場合は動作しないことが

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

注、:だから、問題の例は、関数のパラメータリストの後-> decltype ...句をドロップするだけで、必要に応じてうまく動作するように調整することができます関数に現れます。これは、すべてのreturnステートメントは同じ型の式を返さなければならないが、すべてのラムダオブジェクトにはコンパイラによって独自の型が与えられているため、式はそれぞれ異なる型を持つからです。

+2

なぜC++ 14の推論型は多型ラムダを省略していますか? 'auto retFun(){return [](auto const&x){return x; }; } ' – sehe