C++11 将std::hash专门化到派生类
我有一个抽象的基类C++11 将std::hash专门化到派生类,c++11,gcc,hash,template-specialization,stdhash,C++11,Gcc,Hash,Template Specialization,Stdhash,我有一个抽象的基类Hashable,可以进行散列的类就是从这个基类派生出来的。现在我想将std::hash扩展到从Hashable派生的所有类 下面的代码应该就是这样做的 #include <functional> #include <type_traits> #include <iostream> class Hashable { public: virtual ~Hashable() {} virtual std::size_t Hash
Hashable
,可以进行散列的类就是从这个基类派生出来的。现在我想将std::hash
扩展到从Hashable
派生的所有类
下面的代码应该就是这样做的
#include <functional>
#include <type_traits>
#include <iostream>
class Hashable {
public:
virtual ~Hashable() {}
virtual std::size_t Hash() const =0;
};
class Derived : public Hashable {
public:
std::size_t Hash() const {
return 0;
}
};
// Specialization of std::hash to operate on Hashable or any class derived from
// Hashable.
namespace std {
template<class C>
struct hash {
typename std::enable_if<std::is_base_of<Hashable, C>::value, std::size_t>::type
operator()(const C& object) const {
return object.Hash();
}
};
}
int main(int, char**) {
std::hash<Derived> hasher;
Derived d;
std::cout << hasher(d) << std::endl;
return 0;
}
#包括
#包括
#包括
类散列{
公众:
虚拟~Hashable(){}
虚拟std::size\u t Hash()const=0;
};
派生类:公共哈希表{
公众:
std::size\u t Hash()常量{
返回0;
}
};
//对std::hash进行专门化,以便对Hashable或从其派生的任何类进行操作
//散列。
名称空间标准{
模板
结构散列{
typename std::enable_if::type
运算符()(常量C和对象)常量{
返回object.Hash();
}
};
}
int main(int,char**){
散列哈希器;
导出d;
std::cout似乎没有合适的方法来完成我想做的事情。我决定使用以下宏为每个派生类编写单独的专门化:
// macro to conveniently define specialization for a class derived from Hashable
#define DEFINE_STD_HASH_SPECIALIZATION(hashable) \
namespace std { \
template<> \
struct hash<hashable> { \
std::size_t operator()(const hashable& object) const { \
return object.Hash(); \
} \
}; \
}
呃,不,代码被破坏了。你不允许在std
中声明新模板。你只能在某些条件下编写现有模板的专门化。你拥有的不是专门化即使我们忽略了关于你是什么的规则,也不允许你在std命名空间中做什么,你的类是一个重新定义n这在任何上下文中都是不允许的,即使它被允许,使用它也会有歧义,因为两个定义都会匹配。你必须为每种类型专门化,或者只为Hashable
专门化,并且只为它的所有派生类型使用std::hash
。这就是为什么我不喜欢模板这样的特性而不是函数通过adl。谢谢你的评论。我怀疑我的解决方案不太符合犹太教标准,事实上,我很惊讶它在gcc 4.8.1中完全有效。我决定为每个派生类编写单独的专门化。
// macro to conveniently define specialization for a class derived from Hashable
#define DEFINE_STD_HASH_SPECIALIZATION(hashable) \
namespace std { \
template<> \
struct hash<hashable> { \
std::size_t operator()(const hashable& object) const { \
return object.Hash(); \
} \
}; \
}
// specialization of std::hash for Derived
DEFINE_STD_HASH_SPECIALIZATION(Derived);