在C++中使用自定义比较功能初始化多集

Initializing multiset with custom comparison function in C++

本文关键字:功能 初始化 比较 自定义 C++      更新时间:2023-10-16

考虑以下比较函数:

bool compare(std::shared_ptr<myObject> &lhs, std::shared_ptr<myObject> &rhs){
   return lhs->value < rhs->value;
}

现在的想法是初始化一个类型std::shared_ptr<myObject>的多集,该集合使用上述函数对元素进行排序。所以从我读到的书中应该这样做:

std::multiset<std::shared_ptr<myObject>, decltype(compare)*> myset{compare};

问题:

我的问题是,在声明中,我理解传递一个函数指针来引用比较函数,但是为什么我们要用{compare}初始化集合?它的重要性是什么,为什么有必要这样做?

因为集合需要一个比较函子来使用。如果不指定一个,它将创建一个默认构造的。在这种情况下,由于您使用的是函数指针类型,因此默认构造的指针将是 null 指针,无法调用;因此,您必须在运行时提供正确的函数指针。

更好的方法可能是使用函数类类型(又名函子类型);然后可以在编译时解析函数调用,并且默认构造的对象将执行正确的操作:

struct compare {
    bool operator()(std::shared_ptr<myObject> &lhs, 
                    std::shared_ptr<myObject> &rhs) const {
        return lhs->value < rhs->value;
    }
};
std::multiset<std::shared_ptr<myObject>, compare> myset;
模板

参数中的decltype(compare)*指定比较器的类型。它没有告诉要使用哪个函数 - 是comparefoobar还是其他什么。因此构造函数参数。

为了访问你的元素,你需要为你的类型提供严格的弱排序函数。

std::multiset具有以下构造函数:

 explicit multiset (const key_compare& comp = key_compare(),
               const allocator_type& alloc = allocator_type());

如您所见,您可以通过将函数指针(或函数对象)传递给构造函数comp来执行此操作。


传递给模板的比较器必须是可以使用函数调用运算符调用的类型。那要么是重载该运算符的类,要么是 lambda 或函数指针的类型。在 set 的 cunstrutor 中,必须传递该类型的实例。因此decltype(compare)*是函数指针类型,&compare是函数指针。