【问题标题】:Explicit Return Type of LambdaLambda 的显式返回类型
【发布时间】:2012-03-26 01:55:08
【问题描述】:

当我尝试编译此代码 (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;
  });
}

我如何指定 lambda 具有“void”返回类型。此外,我如何指定 lambda 具有 'bool' 返回类型?

更新

以下编译。谁能告诉我为什么编译而另一个不编译?

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); }));
}

【问题讨论】:

  • 您可以使用-&gt; 明确指定它,例如[&amp;](double d) -&gt; double { //...
  • 我建议您只隐式捕获您需要的变量(仅[&amp;]...),因为您目前拥有的内容是不必要的冗长。
  • [&amp;expression, &amp;start, &amp;end, &amp;what, &amp;flags]...(你的)与[&amp;]...(我的)。现在告诉我谁更冗长。 ;) [&amp;] 告诉 lambda 通过引用捕获您在 lambda 体内使用的所有内容。它被称为“捕获默认值”。另一个是[=],将通过副本捕获。
  • @Emile:这仅对以某种形式或其他形式超过当前范围的 lambda 很重要,真的,这里肯定不是这种情况。
  • 顺便说一下,C++14 中推导的返回类型 lambda 的约束减少了。可以为主体中具有多个语句的 lambdas 推导返回类型,只要每个返回语句的表达式具有相同的类型,您现在就可以具有多个返回语句的推导返回类型。

标签: c++ visual-c++ lambda c++11 visual-c++-2012


【解决方案1】:

您可以在参数列表后使用-&gt; Type 显式指定 lambda 的返回类型:

[]() -> Type { }

但是,如果 lambda 有一个语句并且该语句是一个 return 语句(并且它返回一个表达式),则编译器可以从该返回的表达式的类型推断返回类型。您的 lambda 中有多个语句,因此它不会推断类型。

【讨论】:

  • 编译器可以这样做,但标准禁止这样做。
  • -1:这不是编译器错误。标准对此非常明确:第 5.1.2 节第 4 段列出了如何扣除以及在什么条件下扣除。
  • 虽然根据最新的草案是不允许的,但我发现它看起来在最终规范中实际上是允许的,对此补丁 gcc.gnu.org/ml/gcc-patches/2011-08/msg01901.html 的评论。任何人都有最终的规范来验证?
  • 我已经广泛使用了 lambda 表达式,但我没有一次明确说明返回类型。即使 lambda 表达式中有多个 return 语句,返回类型的推导(至少在 VS2012 和 VS2013 下)也可以完美地工作。当然,不同的返回语句需要在同一个 lambda 表达式中匹配。例如。诸如“auto f = [](int i) { if(i > 5) return true; return false; };”之类的语句编译没有问题,如果你调用“auto b = f(10);” b 将是 bool 类型,当然是 true;
【解决方案2】:

可以推断出 lambda(在 C++11 中)的返回类型,但仅在只有一个语句且该语句是返回表达式 (例如,初始化列表不是表达式)。如果您有一个多语句 lambda,则返回类型假定为 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;
  })

但实际上,您的第二个表达式更具可读性。

【讨论】:

  • 很好的例子; nitpick:你的函数调用最后是否缺少);
【解决方案3】:

仍然返回时可以有多个语句:

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

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

【讨论】:

  • 逗号是一个令人反感的运算符。它使不知道其存在或优先级的人感到困惑。海事组织从来没有有效的用途。它总是可以通过更多的功能或更好的组织代码来避免。
  • @jheriko 同意,我的答案的存在只适用于那些真正想要独立的单线解决方案的人 XD(它仍然是单线,对吗?)。逗号真的不明显,没有人会把整个 main 方法放在这种形式中。
  • 当然,你肯定给出了一个有效的答案,我只是不喜欢做任何事情来鼓励甚至展示不良做法。一旦人们知道逗号是一个运算符,它就会倒计时,直到他们开始滥用它,而一个更长的倒计时,直到他们学得更好。 :)
  • @jheriko 我曾经在成员初始化列表中看到过它有一次有趣的用途,但如果我没记错的话,那只是为了搞砸。
  • 啊,但是读者至少没有首先查看逗号运算符是否可以重载。那会是什么大恶呢?
猜你喜欢
  • 2019-04-20
  • 1970-01-01
  • 1970-01-01
  • 2014-02-23
  • 2021-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多