使用 std::function 作为比较器时函数调用错误

问题描述 投票:0回答:2

我在我的集合中使用 lambda 而不是比较器类,但我遇到了问题。

我有这样的东西:

class Processor {
    
private:
    const function<bool(std::string, std::string)> _lenComp = [](string a, string b) { return a != b && a.size() >= b.size(); };
    set<string, decltype(_lenComp)> _inputSet;

// ...
    
public:
    Processor() : _inputSet() {
    }

    void addLine(string line) {
        _inputSet.insert(line);
    }
    

当我创建

Processor
实例并调用
addLine
2 次时,我收到错误的函数调用异常。 如何正确初始化此类?

c++ lambda std-function
2个回答
2
投票

decltype(_lenComp)
function<bool(std::string, std::string)>
,它是一个空的
std::function
,所以在调用它时会收到错误的呼叫。

你想要的是存储在其中的 lambda 的类型,你应该用

static constexpr auto
来定义它,因为你不允许知道 lambda 的类型。

class Processor {
    
private:
    static constexpr auto _lenComp = [](string a, string b) { return a != b && a.size() >= b.size(); };
    set<string, decltype(_lenComp)> _inputSet;
};

1
投票

扩展另一个答案:在这一行中,lambda 的类型和

_lenComp
的类型不同:

const function<bool(std::string, std::string)> _lenComp = [](string a, string b) { return a != b && a.size() >= b.size(); };

std::function<bool(string, string)>
是一个通用的包装函子,它可以保存任何类型的返回 bool 并接受两个字符串的函数,无论是 lambda、常规函数还是静态方法。您可以重新分配此容器包装的实际实现。

您所做的是创建一个具有不透明(隐藏)类型的 lambda 并将其存储在包装器的实例中。然后将 wrapper 的类型传递到

std::set
模板中。

_inputSet
被构造时,它不知道你的 lambda。它将构造一个给定的比较器类型的新实例,在您的例子中是一个
std::function
。默认构造的
std::function
是空的。

如果您想保留

std::function
,则上述问题的另一个修复方法是在构造集合时将已有的比较器实例传递给集合,如下所示:

// ...

    const function<bool(std::string, std::string)> _lenComp = [](string a, string b) { return a != b && a.size() >= b.size(); };
    set<string, decltype(_lenComp)> _inputSet;

public:
    Processor(): _inputSet({}, _lenComp) {}

// ...
© www.soinside.com 2019 - 2024. All rights reserved.