要在std::unordered_set
中使用自定义类型,我必须选择。
1)为我的类型实现==
运算符,并专门化std::hash
struct MyType {
int x;
bool operator==(const MyType& o) {
return this.x == o.x;
}
};
namespace std
{
template<>
struct hash<MyType> {
size_t operator()(const MyType& o) const {
return hash<int>()(o.x);
}
};
}
std::unordered_set<MyType> mySet;
或2),提供函子类:
struct MyTypeHash {
size_t operator()(const MyType& o) const {
return std::hash<int>()(o.x);
}
};
struct MyTypeCompare {
bool operator()(const MyType& o1, const MyType& o2) const {
return o1.x == o2.x;
}
};
std::unordered_set<MyType, MyTypeHash, MyTypeCompare> mySet;
第二种方法让我为std::unordered_set
的每个新实例选择新的行为,而第一种方法使它作为类型本身的一部分的行为将始终相同。
现在,如果我知道我只想要一种行为(我永远不会为MyType
定义两个不同的比较器),哪种方法更可取?两者之间还有什么其他区别?
将行为附加到类型允许使用类似代码
template<template<class> Set,class T>
auto organizeWithSet(…);
/* elsewhere */ {
organizeWithSet<std::unordered_set,MyType>(…);
organizeWithSet<std::set,MyType>(…);
}
显然不能传递自定义函数对象。
也就是说,可以定义
template<class T>
using MyUnorderedSet=std::unordered_set<T, MyTypeHash,MyTypeCompare>;
并且使用它作为模板模板参数,尽管它引入了另一个名称,并且可能被认为不太可读。
否则,您必须考虑到operator==
同时是std::unordered_set
和std::find
的默认值;如果您希望达到这些目的的等效性有所不同,则可能需要命名比较器。另一方面,如果足够的话,C ++ 20甚至可以只用=default
来定义它。