STL 中使用的 C++ 自定义比较类型(函数谓词与 less 结构)

C++ custom Compare types used in STL (function predicate vs. less struct)

我查看了std::sort和std::priority_queue的原型,模板中定义的自定义比较类型看起来很像。

template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp );

template <class T, class Container = vector<T>,
  class Compare = less<typename Container::value_type> > class priority_queue;

但实际上它们是不同的,std::sort接受一个函数谓词,而std::priority_queue接受一个结构(一种类型)。 为什么?提前致谢!

struct cmp {
    bool operator() (const int &a, const int &b) {
        return a < b;
    }
};

vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(1);
// this works
sort(v.begin(), v.end(), [](const int &a, const int &b) -> bool {
    return a < b;
});
// this not works
// sort(v.begin(), v.end(), cmp);
cout << v[0] << endl;

// this works
priority_queue<int, cmp> q;
// this not works
// priority_queue<int, [](const int &a, const int &b) -> bool {
//     return a < b;
// }> q;
q.push(2);
q.push(3);
q.push(1);
cout << q.top() << endl;

其实是一样的,区别是一个是class模板,一个是函数模板。

以下是您可以使用优先级队列执行的操作:

auto comp = [](const int& a, const int& b) { return a < b; };
priority_queue<int, std::vector<int>, decltype(comp)> q(comp);

不同之处在于,对于函数模板,编译器将从提供的函数参数中推导出模板参数,而对于 class 模板则不会。所以你必须明确地提供类型,并且使用 lambda(它有一个匿名类型),这很烦人。

不同之处在于 sort 是一个 function 模板,因此 Comparatortemplate 参数可以从 function 参数的类型推导出来。当你这样称呼它时:

sort(v.begin(), v.end(), [](const int &a, const int &b) -> bool {
    return a < b;
});

然后 Comparator 的参数被推断为 lambda 闭包对象的 类型

另一方面,

priority_queue 是一个 class 模板。没有类型扣除。您在 q 的类型中指定 Compare 的模板参数,之后,您只能提供适当类型的函数参数(给构造函数)。

要将 lambda 与优先级队列一起使用,您需要了解其类型:

auto compare = [](const int &a, const int &b) -> bool {
  return a < b;
};

std::priority_queue<int, std::vector<int>, decltype(compare)> q(compare);

您试图将 lambda 表达式 作为参数传递给模板 type 参数。这是行不通的。用 sort 做同样的事情也行不通:

sort<vector<int>::iterator, [](const int &a, const int &b) -> bool {
    return a < b;
}>(/*...*/);