ラムダの明示的な戻り型


91

このコード(VS2010)をコンパイルすると、次のエラーが発生します。 error C3499: a lambda that has been specified to have a void return type cannot return a value

void DataFile::removeComments()
{
  string::const_iterator start, end;
  boost::regex expression("^\\s?#");
  boost::match_results<std::string::const_iterator> what;
  boost::match_flag_type flags = boost::match_default;
  // Look for lines that either start with a hash (#)
  // or have nothing but white-space preceeding the hash symbol
  remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line)
  {
    start = line.begin();
    end = line.end();
    bool temp = boost::regex_search(start, end, what, expression, flags);
    return temp;
  });
}

ラムダに「void」戻り値型があることをどのように指定しましたか?さらに、ラムダの戻り値の型が「ブール」であることをどのように指定できますか?

更新

以下がコンパイルされます。誰かがなぜそれがコンパイルし、他の人がしないのか教えてもらえますか?

void DataFile::removeComments()
{
  boost::regex expression("^(\\s+)?#");
  boost::match_results<std::string::const_iterator> what;
  boost::match_flag_type flags = boost::match_default;
  // Look for lines that either start with a hash (#)
  // or have nothing but white-space preceeding the hash symbol
  rawLines.erase(remove_if(rawLines.begin(), rawLines.end(), [&expression, &what, &flags](const string& line)
  { return boost::regex_search(line.begin(), line.end(), what, expression, flags); }));
}

6
あなたは明示的にそれを指定することができます->例えば、[&](double d) -> double { //...
フレキソ

2
[&]...現在必要な変数は不必要に冗長であるため、必要な変数(のみ)を暗黙的にキャプチャすることをお勧めします。
Xeo

2
[&expression, &start, &end, &what, &flags]...(あなたのもの)vs [&]...(私のもの)。だれがより冗長であるか教えてください。;)[&]参照によってラムダ本体内で使用するすべてのものをキャプチャするようにラムダに指示します。これは「キャプチャーデフォルト」と呼ばれます。もう1つは[=]、コピーでキャプチャします。
Xeo

1
@ Xeo、Effective Modern C ++、アイテム31は、参照のぶら下がりを避けるために、明示的にキャプチャすることを推奨しています。私はそれを何回か私に怠け者の罰として噛まれました...ええと、簡潔です。:-)
Emile Cormier

2
ちなみに、C ++ 14では、戻り値型の推定ラムダに対する制約が緩和されています。本文に複数のステートメントがあるラムダの戻り型を推定できます。各戻りステートメントの式が同じ型である限り、複数の戻りステートメントを持つ推定戻り型を使用できます。
Anthony Hall

回答:


188

-> Type引数リストの後にを使用して、ラムダの戻り値の型を明示的に指定できます。

[]() -> Type { }

ただし、ラムダに1つのステートメントがあり、そのステートメントがreturnステートメントである(そして式が返される)場合、コンパイラーは、返された1つの式のタイプから戻りタイプを推定できます。ラムダに複数のステートメントがあるため、型が推定されません。


4
コンパイラはそれを行うことができますが、標準ではそれを行うことを禁止しています。
ヨハネスシャウブ-litb

9
-1:これはコンパイラのバグではありません。この基準は非常に明確です。セクション5.1.2のパラグラフ4では、控除がどのように行われ、どのような条件下で行われるかについて説明しています。
Nicol Bolas

2
最新のドラフトでは許可されていませんが、このパッチのコメントgcc.gnu.org/ml/gcc-patches/2011-08/msg01901.htmlによって最終仕様で実際に許可されているように見えます。誰かが検証する最終仕様を持っていますか?
Eelke 2013

2
私はラムダ式を広範囲に使用しており、戻り値の型を明示的に述べたことはありません。ラムダ式に複数のreturnステートメントがある場合でも、(少なくともVS2012とVS2013で)戻り値の型の推定は問題なく機能します。もちろん、さまざまなreturnステートメントが同じラムダ式内で一致する必要があります。たとえば、「auto f = [](int i){if(i> 5)return true; return false;};」などのステートメント 問題なくコンパイルされ、 "auto b = f(10);"を呼び出すと bはbool型で、もちろんtrueです。
スプライト2015年

1
return nullptr;他の方法で返されるポインターの型としては有効ですが、型の推測にレンチを投げることができます。
グラウル、2015

16

ラムダの戻り値の型(C ++ 11の場合)は推測できますが、ステートメントが1つだけあり、そのステートメントがreturn式を返すステートメントである場合のみです(たとえば、初期化子リストは式ではありません)。複数ステートメントのラムダがある場合、戻り値の型はvoidであると見なされます。

したがって、これを行う必要があります。

  remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line) -> bool
  {
    start = line.begin();
    end = line.end();
    bool temp = boost::regex_search(start, end, what, expression, flags);
    return temp;
  })

しかし、実際には、2番目の式の方がはるかに読みやすくなっています。


いい例です。nitpick:関数呼び出し);が最後に欠落していますか?
kevinarpe 2017年

6

まだ戻るときに、複数のステートメントを持つことができます。

[]() -> your_type {return (
        your_statement,
        even_more_statement = just_add_comma,
        return_value);}

http://www.cplusplus.com/doc/tutorial/operators/#comma


4
コンマは反抗演算子です。その存在や優先レベルを認識していない人々を混乱させます。どちらの有効な用途もありません。関数を増やすか、コードを整理することで、常に回避できます。
jheriko 2016年

@jheriko同意します。私の答えの存在は、独立した1ライナーソリューションXDを本当に望んでいる人だけのためです(それはまだ1行ですよね?)。コンマは目立たないので、メインメソッド全体をこのフォームに入れることはできません。
バレン

1
確かに、あなたは確かに有効な答えを出しています。私は、悪い習慣を奨励したり、実証したりするために何かをすることのファンではありません。カンマが演算子であることを知ると、乱用を開始するまでのカウントダウンと、よりよく学ぶまでのカウントダウンです。:)
jheriko 2016年

@jherikoこ​​れは、メンバーの初期化リストで一度興味深い使用になっているのを見たことがあります。
ジャスティン時間-2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.