2016-02-20 72 views
3

比方說,我們有下面的類:定義的std ::哈希類模板的枚舉成員

template <int i> 
class S { 
public: 
    enum class E : signed char {a, b, c}; 
    // ... 
}; 

現在我想爲E.散列函數以下工作:

namespace std { 
template<> 
struct hash<typename S<3>::E> { 
    size_t operator()(typename S<3>::E const& e) const { return 0; } 
}; 
} 

但是,如果我讓一般它不會:

namespace std { 
template<int i> 
struct hash<typename S<i>::E> { 
    size_t operator()(typename S<i>::E const& e) const { return 0; } 
}; 
} 
// error C2764: 'i': template parameter not used or deducible in partial specialization 'std::hash<S<i>::E>' 

我怎樣才能確保始終能夠哈希的s :: E代表所有我?

+2

如果所有的'S '有'E'是其他單一類型的typedef? 「我」無法在一般意義上理解。這不完全相同,但在這裏有一些類似的答案。找到一個:http://stackoverflow.com/questions/6060824/c-template-argument-can-not-be-deduced – chris

回答

4

typename S<3>::E表示特定類型。對於這種類型,宣佈std::hash的顯式專門化是很好的。如果該類型曾被用作std::hash的模板參數,那麼將使用您的顯式特化。

在另一方面,也沒有辦法,你偏特

template<int i> 
struct hash<typename S<i>::E> 

都不能使用。正如錯誤所述,i是不可扣除的。對於任何給定的T,編譯器無法確定std::hash<T>是否應使用您的部分特化,因爲它無法確定是否存在i,因此typename S<i>::ET的類型相同。如果i是在推斷上下文中使用,如:

template<int i> 
struct hash<S<i>> 

這將是不同的,因爲那麼編譯器可以簡單地嘗試推斷i。編譯器當然可以知道給定類型是否爲S<i>,其中S是其已知的模板。如果TS<i>對於某些i,那麼扣除成功,否則它失敗並且專用性被忽略。在未推導的上下文中,編譯器無法分辨。

如何解決?如果E是類的類型,我會建議使它成爲一個不會嵌套在S內的模板。然後你可以專門爲專門std::hash。但是,你不能擁有枚舉模板,所以沒有。你可能只需要一個非模板枚舉和一個該類型的哈希專用化,然後有S<i>::E是對所有i枚舉的typedef。如果您不希望用戶依賴S<i>::E與所有i相同的事實,則可以說S<i>::E的定義未指定。

+0

總而言之,一個非推斷的上下文,對吧? – AndyG

+0

對。那麼如何確保我始終可以散列S :: E適用於所有我? – Petter

+0

@Petter看編輯 – Brian