【问题标题】:C++ custom Compare types used in STL (function predicate vs. less struct)STL 中使用的 C++ 自定义比较类型(函数谓词与 less 结构)
【发布时间】:2015-02-06 10:18:37
【问题描述】:

我检查了 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(a type)。 为什么?提前致谢!

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;

【问题讨论】:

    标签: c++ c++11 stl comparator


    【解决方案1】:

    区别在于sort 是一个function 模板,因此Comparatortemplate 参数可以从function 参数。当你这样称呼它时:

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

    那么Comparator 的参数被推断为lambda 闭包对象的类型

    另一方面,

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

    要将 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;
    }>(/*...*/);
    

    【讨论】:

    • 我会添加一个警告,你不想在头文件中做这样的事情,因为很容易违反 ODR(一个定义规则),因为每个 lambda 都是一个不同的类型,即使您在多个翻译单元中包含相同的标题。
    【解决方案2】:

    其实是一样的,不同的是一个是类模板,一个是函数模板。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2021-07-12
      • 1970-01-01
      • 2012-02-11
      • 2021-03-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多