如何从lambda中的函数返回?

fre*_*low 16 c++ lambda return control-flow c++11

考虑以下玩具代码以确定范围是否包含元素:

template<typename Iter, typename T>
bool contains1(Iter begin, Iter end, const T& x)
{
    for (; begin != end; ++begin)
    {
        if (*begin == x) return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

(是的,我知道,标准库中已有完美的算法,但这不是重点.)

我怎么用for_each和lambda 写同样的东西?以下不起作用......

template<typename Iter, typename T>
bool contains2(Iter begin, Iter end, const T& x)
{
    std::for_each(begin, end, [&x](const T& y) {
        if (x == y) return true;
    });
    return false;
}
Run Code Online (Sandbox Code Playgroud)

...因为那只会从lambda返回,而不是从函数返回.

我是否必须抛出异常以摆脱lambda?同样,对于这个特定问题可能有十几个更好的解决方案,根本不涉及lambda,但这不是我要求的.

Nic*_*las 7

std::for_each如果你想尽早结束循环,那么你不应该使用算法.它似乎你想要std::find_if或类似的东西.您应该使用最适合您任务的算法,而不仅仅是您熟悉的算法.


如果你真的,真的,真的必须尽早从算法"返回",你可以 -

警告:接下来是一个非常非常糟糕的想法,你几乎不应该这样做.实际上,查看代码可能会让你的脸变得脆弱.你被警告了!

抛出异常:

bool contains2(Iter begin, Iter end, const T& x)
{
  try {
    std::for_each(begin, end, [&x](const T& y) {
        if (x == y)
          throw std::runtime_error("something");
    });
  }
  catch(std::runtime_error &e) {
    return true;
  }
  return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 你基本上只是在没有问号的情况下重新描述问题.他说*他知道有更合适的`std`算法,他提到了抛出异常的可能性. (7认同)

Kon*_*lph 7

我怎么用for_each和lambda 写同样的东西?

你不能(抛开例外).你的函数不是for-each循环的同构(=一种映射),就像那样简单.

相反,您的功能是通过缩减来描述的,因此如果您想使用高阶函数来替换它,请使用缩小而不是贴图.

如果 C++ 具有适当的通用性,reduce那么您的算法将如下所示:

template<typename Iter, typename T>
bool contains2(Iter begin, Iter end, const T& x)
{
    return stdx::reduce(begin, end, [&x](const T& y, bool accumulator) {
        return accumulator or x == y;
    });
}
Run Code Online (Sandbox Code Playgroud)

当然,如果减少适当地专门用于布尔结果值,这只会提前退出,以便短路.

唉,就我看来,C++并没有提供这样的功能.有accumulate但不会短路(它不能- C++不知道操作的内部拉姆达短路,并且不递归实现).