为什么需要将比较函数类型指定为模板参数?

时间:2019-09-30 14:53:41

标签: c++ stl

对于C ++中的关联容器,例如set,map等,我们需要提供自定义键比较器类型作为模板参数,如下所示。

bool compareMyType(const MyType& a, const MyType& b);

set<MyType, decltype(compareMyType)*> my_set(compareMyType); // OK
set<MyType> my_set(compareMyType); // ERROR

为什么要这样做?为什么不能通过键的类型推导比较器功能的类型?

3 个答案:

答案 0 :(得分:4)

与函数不同,类模板没有部分推论。如果为类模板提供模板参数,则需要提供所有非默认参数,在set的情况下,您需要提供比较类型,因为它的默认值为std::less<T>,即函数指针不能转换为。

有人提议部分扣除,但被拒绝了,目前添加到CTAD的唯一事情是它将通过别名工作。

答案 1 :(得分:2)

您的问题已得到回答,所以这只是解决问题的方法的输入:

您可以为您的类型提供operator<,以避免每次在set中使用它时都必须为其提供较少的函子。

#include <iostream>
#include <set>

struct MyType {
    int value;
};

// added operator<
bool operator<(const MyType& l, const MyType& r) {
    return l.value < r.value;
}

int main() {
    std::set<MyType> my_set = {{3}, {2}, {1}};
    for(const MyType& m : my_set) 
        std::cout << ' ' << m.value;
    std::cout << "\n";
}

输出:

 1 2 3

如果您想将其用于基于哈希的容器(例如unordered_set),则可以类似地添加一个std::hash<MyType>类,该类将默认用于您的类型。

答案 2 :(得分:1)

因为比较器不一定是一个函数(函数指针,偶)。实际上,该参数的默认值为std::less<Key>,这是带有operator()的类模板。但是您可以传递可以用两个MyType const&调用的任何东西的类型并返回bool,因此需要指定该东西实际上是什么。