2
我有一個抽象基類Hashable
可以散列的類派生自。我現在想將std::hash
擴展到從Hashable
派生的所有類。專門化派生類的std :: hash
下面的代碼應該做到這一點。
#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;
}
上面的代碼工作完全與GCC 4.8.1預期,但是當我嘗試用gcc 4.7.2編譯它,我得到如下:
$ g++ -std=c++11 -o test test_hash.cpp
test_hash.cpp:22:8: error: redefinition of ‘struct std::hash<_Tp>’
In file included from /usr/include/c++/4.7/functional:59:0,
from test_hash.cpp:1:
/usr/include/c++/4.7/bits/functional_hash.h:58:12: error: previous definition of ‘struct std::hash<_Tp>’
/usr/include/c++/4.7/bits/functional_hash.h: In instantiation of ‘struct std::hash<Derived>’:
test_hash.cpp:31:24: required from here
/usr/include/c++/4.7/bits/functional_hash.h:60:7: error: static assertion failed: std::hash is not specialized for this type
任何人能想到的方式使std::hash
這個專業化工作從Hashable
與gcc 4.7.2派生的任何類?
爾沒有該代碼被打破。你不能在'std'中聲明新的模板。您只能在特定條件下編寫現有模板的專業化。你在那裏沒有專業化 –
即使我們忽略了關於你是什麼樣的規則並且不允許你在std命名空間中做的規則,你的類是一個重定義,它在任何上下文中都是不允許的,即使它被允許,因爲兩個定義都會匹配,所以這是不明確的。你將不得不針對每種類型進行專門化,或者只針對'Hashable',並且只對所有派生類型使用'std :: hash'。這就是爲什麼我不喜歡通過adl的模板而不是函數的特性。 –
John5342
感謝您的意見。我懷疑我的解決方案不是很好,我真的很驚訝,它在gcc 4.8.1中都可以工作。我決定爲每個派生類編寫單獨的專業化。 – Flecto