使用非标准签名定义自定义映射比较器

3
假设有一个以指针为键的地图。要进行底层对象的深度比较,可以按以下方式编写自定义比较器:
#include <map>
#include <memory>

bool compare(std::unique_ptr<int> lhs, std::unique_ptr<int> rhs){
    return *lhs<*rhs;
}

int main(){
    std::map<std::unique_ptr<int>, short, bool (*)(std::unique_ptr<int>, std::unique_ptr<int>)> elements(compare);
}

我可以理解,但是为什么我需要明确传递比较回调函数的类型,因为它是由映射键的类型强制实施的?为什么不能按照以下方式创建映射,因为它的签名应该是已知的:

std::map<std::unique_ptr<int>, short> elements(compare);

是否有情况需要使用不同签名定义比较函数?

编辑:

我认为我已经回答了最后一个问题。 在某些情况下,我可以编写如下内容:

#include <map>
#include <memory>

bool compare(std::unique_ptr<BaseClass> lhs, std::unique_ptr<BaseClass> rhs){
    return *lhs<*rhs;
}

int main(){
    std::map<std::unique_ptr<DerivedClass>, short, bool (*)(std::unique_ptr<BaseClass>, std::unique_ptr<BaseClass>)> elements(compare);
}

但是它并没有解释为什么默认情况下不使用精确签名。
2个回答

3
为什么不可能通过以下方式创建地图呢,因为其签名应该是已知的。但是它并非唯一已知的,该函数是至少两种类型地图的有效初始化程序。
std::map<std::unique_ptr<int>, short, bool (*)(std::unique_ptr<int>, std::unique_ptr<int>)>
std::map<std::unique_ptr<int>, short, bool (&)(std::unique_ptr<int>, std::unique_ptr<int>)>

一个指向函数的指针或引用在这里都能很好地工作。两者没有本质上的优劣,那么如何唯一确定类型呢?没有马上让人信服的理由支持一方超过另一方。
值得一提的是,稍微更惯用的使用方式是反过来的std::map。即,不是从比较对象中确定类型,而是使用可以初始化对象的用户定义类型。例如:
struct compare {
    bool operator()(std::unique_ptr<int> lhs, std::unique_ptr<int> rhs){
        return *lhs<*rhs;
    }
};

std::map<std::unique_ptr<int>, short, compare> elements;

1
比较器的类型与键的类型并没有任何关系。比较器不一定是一个函数,它也可以是一个重载了operator()的类。
事实上,第三个模板参数有一个默认参数,即一个名为std::less<Key>的类的实例化。也就是说,std::map<std::unique_ptr<int>, short>std::map<std::unique_ptr<int>, short, std::less<std::unique_ptr<int>>>的简写形式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接