13

私の本にはこう書かれています。

戻り型 return void を指定しない単一の return ステートメント以外のものを含む関数本体を持つラムダ。

でもこれは:

auto f = []{
  int i=0; i++;
  return std::string("foo");
};
std::cout << f() << std::endl;

実際には「foo」をコンパイルして出力しますが、そのラムダ expr には複数の return ステートメントがあるため、「-> std::string」を戻り値の型として手動で指定していないため、void を返す必要があります。

何が起きてる?

Clang 3.2に基づいて、最新のXcode 4.6でAppleのコンパイラを使用しています。

clang --バージョン

Apple LLVM バージョン 4.2 (clang-425.0.24) (LLVM 3.2svn ベース) ターゲット: x86_64-apple-darwin12.2.0 スレッド モデル: posix

4

5 に答える 5

6

この本は、標準の草案 n3290 の規則を正確に反映しています。おそらく、コンパイラが別のドラフトを実装したのでしょう。

セクション 5.1.2p4 では、草案は次のようになっています。

lambda-expressionにTrailing-return-typeが含まれていない場合は、trailing-return-typeが次の型を示しているかのようになります。

  • 複合ステートメント{ attribute-specifier-seq opt return の形式の場合; } 、左辺値から右辺値への変換、配列からポインターへの変換、および関数からポインターへの変換後に返される式の型。
  • それ以外の場合は無効です。

構文構造attribute-specifier-seqは、alignasまたは二重括弧で囲まれた属性です。変数宣言ではありません。

C++11 の公開に続いて作成されたドラフト n3485 (つまり、C++1y に向けて進行中) には、同じ文言が含まれています。n3290より前のドラフトで別のルールがあったかどうかはわかりません。

于 2013-02-06T20:43:41.023 に答える
3

一般的なコンパイラ (gcc、Visual Studio) を使用する場合、例のように、コンパイラが明確に決定できる限り、通常は戻り値の型を指定する必要はありません。

次の例は、明示的な戻り値の型情報を必要とするラムダを示しています。

auto lambda = [](bool b) -> float
    { 
        if (b) 
            return 5.0f; 
        else 
            return 6.0; 
    };

私はこの問題について Bjarne Stroustrup に尋ねました。彼のコメントは次のとおりです。

I do not know if C++11 allows the deduction of the return type is there are several return statements with identical return type. If not, that's planned for C++14.

于 2013-02-06T20:41:14.193 に答える
1

質問の引用から何を作成すればよいかわかりませんが、宣言子または戻り値の型のないラムダについてC++ 11標準が述べていることは次のとおりです。

ラムダ式にラムダ宣言子が含まれていない場合は、ラムダ宣言子が () であるかのようになります。ラムダ式にトレーリング リターン タイプが含まれていない場合、トレーリング リターン タイプが次のタイプを示しているかのようになります (5.1.2p4)。

— 複合ステートメントが { 属性指定子-seqopt 戻り式 ; の形式の場合。左辺値から右辺値への変換 (4.1)、配列からポインターへの変換 (4.2)、および関数からポインターへの変換 (4.3) の後に返される式の型。

— それ以外の場合は無効です。

于 2013-02-06T20:46:01.307 に答える
0

ドラフト n3485 は、コンパイラが戻り値の型を明確に決定できる場合、ラムダがそれを指定しないことを許可することを示しています。

于 2013-02-06T20:44:58.217 に答える