【问题标题】:Sort a container with a lambda with captured value使用具有捕获值的 lambda 对容器进行排序
【发布时间】:2019-10-23 06:52:18
【问题描述】:

我正在尝试声明一个带有比较函数的 std::set,以通过使用带有捕获值的 lambda 来指定元素的顺序。

我尝试使用捕获的值创建一个 lambda,并将该 lambda 作为模板化参数传递给 std::set。 我也尝试过使用仿函数,但也无法正常工作。

//Using a lambda

int value = 3; //This is not known at compile time

std::function cmp = [&value](int a, int b){
   return value > 123 ? a < b : a >= b;
};

std::set<int, cmp> mySet;

// Using a functor

class Cmp{
    int value;
public:
    Cmp(int value) : value(value){}; 
    bool operator()(const int&a, const int& b){
        return value > 123 ? a < b : a >= b;
    }
};

int val = 3; //This is not known at compile time

Cmp cmp(val);
set<int, cmp> mySet;

使用 lambda 时出现此错误:

注意:lambda 闭包类型有一个已删除的默认构造函数

使用仿函数时的这个:

错误:没有匹配的函数调用'Cmp::Cmp()'

【问题讨论】:

    标签: c++


    【解决方案1】:

    您不能在模板参数中传递运行时变量。

    std:setCompare 模板参数需要一个类型名,而不是一个变量。与类型名匹配的实际比较函数可以传递给set::set构造函数。

    试试这个:

    //Using a lambda
    
    int value = 3; //This is not known at compile time
    
    auto cmp = [&value](int a, int b){
       return value > 123 ? a < b : a >= b;
    };
    
    std::set<int, decltype(cmp)> mySet(cmp);
    
    //Using a functor
    
    class MySetComparer{
        int value;
    public:
        MySetComparer(int value) : value(value) {}
        bool operator()(int a, int b) const {
            return value > 123 ? a < b : a >= b;
        }
    };
    
    int val = 3; //This is not known at compile time
    
    MySetComparer cmp(val);
    set<int, MySetComparer/*decltype(cmp)*/> mySet(cmp);
    

    注意:无论哪种方式,请注意您的比较器对a &gt;= b 的使用打破了标准 C++ 容器使用的Compare 要求的strict weak ordering

    应用于满足比较类型的对象的函数调用操作的返回值,当上下文转换为bool时,如果调用的第一个参数,则产生true出现在此类型引发的严格弱排序关系中的第二个之前,否则出现false

    a &lt; b 满足该要求,但a &gt;= b 不满足,当value &gt; 123 不为真时,这将导致您的代码在运行时出现Undefined Behavior

    【讨论】:

    • 你应该提到使用a &gt;= b会导致UB
    • 非常感谢,我确实忘记了decltype,但我不知道你必须将对象传递给构造函数!再次感谢!
    • @Slava 我添加了它
    猜你喜欢
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-21
    • 2012-09-26
    • 2017-10-17
    相关资源
    最近更新 更多