C++ Lambda表达式,“error: expected expression”

3

我正在尝试在C++中重现Java的Streams API,并已经编写了以下程序。

#include <iostream>

using namespace std;

template <typename E>
class stream {
    virtual void collect(void (*consumer) (E)) = 0;
    virtual bool anyMatch(bool (*predicate) (E)) {
        bool found = false;
        collect([&found](E obj) -> { if (predicate(obj)) {found = true} });
        return found;
    }
};

int main() {
    return 0;
}

但是当我试图使用g ++编译它时:

enter image description here

我的lambda表达式哪里出了错?它应该提供一个函数(消费者),该函数将使用谓词(一个函数)测试给定的E,如果评估结果为true,则设置found为true。


是的,我主要只是想学习C++。 - Phoenix
3
只有没有捕获的lambda表达式才能转换为普通函数指针。带有捕获的lambda表达式则不可能实现这一点,因为它没有地方来存储这些捕获。 - Igor Tandetnik
有没有其他数据类型可以用来保存捕获lambda? - Phoenix
1
std::function - Igor Tandetnik
除了其他评论之外,你的带有lambda的那一行代码至少有三个问题。尝试这样写:collect([&found, predicate](E obj) { if (predicate(obj)) {found = true;} }); - Ami Tavory
显示剩余5条评论
1个回答

2

你的代码中存在几个不同的问题:

  1. 你所贴出的错误提示表明你正在使用早期的 C++11 编译模式。Lambda 表达式是在 C++11 中引入的。

  2. 存在一些语法错误。你的 Lambda 表达式尾部返回类型缺少类型,并且在 Lambda 表达式主体中缺少分号。

  3. 你试图将一个非捕获 Lambda 表达式转换为函数指针。这是不可能的,因为捕获变量需要一个状态/上下文。


你的代码不是有效的C++代码 - 语法有误。这里有一个具有有效语法的版本
template <typename E>
class stream
{
    virtual void collect(void (*consumer)(E)) = 0;
    virtual bool anyMatch(bool (*predicate)(E))
    {
        bool found = false;
        collect([predicate, &found](E obj)
            {
                if(predicate(obj))                    
                    found = true;                    
            });

        return found;
    }
};

然而,该代码无法编译,因为非捕获式lambda不能转换为函数指针。如果允许这样做,那将是一场灾难的配方,因为关于被捕获变量的信息将会丢失。您可以使用 std::function,它会擦除lambda的类型并处理带有非空捕获列表的lambda,但代价是内存/运行时开销:
template <typename E>
class stream
{
    virtual void collect(std::function<void(E)> consumer)
    {
        (void)consumer;
    }

    virtual bool anyMatch(std::function<bool(E)> predicate)
    {
        bool found = false;
        collect([predicate, &found](E obj)
            {
                if(predicate(obj))                    
                    found = true;                    
            });

        return found;
    }
};

它只编译是因为你从未实例化“stream”。一旦你这样做,它就会失败 - Igor Tandetnik
@IgorTandetnik:是的 - 我所说的“它可以编译”是指“正确/可解析的C++语法”。我会澄清这个答案。 - Vittorio Romeo
@IgorTandetnik:我改进了答案。如果还有误导,请告诉我。 - Vittorio Romeo
@LightnessRacesinOrbit: 它确实可以[](int obj) -> { (void) obj; } 不是有效的 lambda 语法 - 他忘记了返回类型。 - Vittorio Romeo
@LightnessRacesinOrbit 同时,if (predicate(obj)) {found = true} 也不是有效的语法。在 found = true 后面缺少一个分号。 - Vittorio Romeo
@VittorioRomeo 我不知道为什么我写了那个。 - Lightness Races in Orbit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接