2014-02-20 114 views
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派生的任何類?

+1

爾沒有該代碼被打破。你不能在'std'中聲明新的模板。您只能在特定條件下編寫現有模板的專業化。你在那裏沒有專業化 –

+2

即使我們忽略了關於你是什麼樣的規則並且不允許你在std命名空間中做的規則,你的類是一個重定義,它在任何上下文中都是不允許的,即使它被允許,因爲兩個定義都會匹配,所以這是不明確的。你將不得不針對每種類型進行專門化,或者只針對'Hashable',並且只對所有派生類型使用'std :: hash '。這就是爲什麼我不喜歡通過adl的模板而不是函數的特性。 – John5342

+0

感謝您的意見。我懷疑我的解決方案不是很好,我真的很驚訝,它在gcc 4.8.1中都可以工作。我決定爲每個派生類編寫單獨的專業化。 – Flecto

回答

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); 
相關問題