2011-11-18 68 views
8

我想定義std::tr1::hash<boost::tuple<A,B,C> >。但是當我給出完整的即時消息時,我得到一個不會出現的錯誤。下面的代碼在tr1 :: hash中使用boost :: tuple

namespace std{ 

namespace tr1{ 
template<typename A, typename B, typename C> 
struct hash<boost::tuple<A,B,C> >{ 
    size_t operator()(const boost::tuple<A,B,C> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.get<0>()); 
     boost::hash_combine(seed, t.get<1>()); 
     boost::hash_combine(seed, t.get<2>()); 
     return seed; 
    } 
}; 

template<> 
struct hash<boost::tuple<int,int,int> >{ 
    size_t operator()(const boost::tuple<int,int,int> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.get<0>()); 
     boost::hash_combine(seed, t.get<1>()); 
     boost::hash_combine(seed, t.get<2>()); 
     return seed; 
    } 
}; 
} 
} 

第一塊給出了這樣的錯誤

unordered.hpp: In member function 'size_t std::tr1::hash<boost::tuples::tuple<A, B, C, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type> >::operator()(const boost::tuples::tuple<A, B, C, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>&) const': 
unordered.hpp:12: error: expected primary-expression before ')' token 
unordered.hpp:13: error: expected primary-expression before ')' token 
unordered.hpp:14: error: expected primary-expression before ')' token 

和第二編譯就好了。第一個模板有什麼問題?我正在使用gcc 4.3.4。

+0

「std :: hash」不是C++ 11的特性嗎?在這種情況下,你也可以使用'std :: tuple'。我相信你錯過了一個'typename'關鍵字。 – AJG85

+0

我認爲'boost :: hash'已經定義爲'boost :: tuple's。如果你使用標準庫,也可以使用'std :: tuple'! –

+0

@ AJG85我使用gcc 4.3.4,其中'hash'仍然在'tr1'中,而'tuple'只在boost中。 –

回答

8

您需要使用.template關鍵字:

template<typename A, typename B, typename C> 
struct hash<boost::tuple<A,B,C> >{ 
    size_t operator()(const boost::tuple<A,B,C> &t) const{ 
     size_t seed = 0; 
     boost::hash_combine(seed, t.template get<0>()); 
     boost::hash_combine(seed, t.template get<1>()); 
     boost::hash_combine(seed, t.template get<2>()); 
     return seed; 
    } 
}; 

這是必需的,因爲t類型取決於三個模板PARAMATERS(等t是類型而定),以及get<0>是一個名字模板專業化。從C++標準 - §14.2/4

當成員模板專業化的名稱出現後。或者 - >在後綴表達式中...並且後綴表達式的對象表達式是依賴於類型的......成員模板名稱必須以關鍵字模板爲前綴。 ...

此要求的存在允許模板在其類型參數已知之前進行分析。

例如,請考慮:

f . set <0> (2 == 3) 

沒有.template規則,這可以解釋爲兩個不同的東西:

//A call to an instantiation of a member function template 
//in this case equivalent to f.template set<0>(false) 
f.set<0>(2 == 3) 
//A series of comparison operations, in this case equivalent to 
//f.set < 0 
f.set <0> (2 == 3) 

實際規則允許f . set <0> (2 == 3)被明確地解析爲一個系列的比較操作。他們還意味着t.get<0>()被解析爲t.get <0>()expected primary-expression意味着在空的()

6

我沒有時間去檢查的事情但是我希望無論是

std::get<0>(t) 

boost::get<0>(t) 

,而不是t.get<0>()

資格的get()即使你在使用命名空間,或者在混合這樣的庫時ADL也會嚴重傷害你。見What are the pitfalls of ADL?

+0

事實上,使用'boost :: get'工作。爲什麼? –

+0

請參閱http://stackoverflow.com/questions/2958648/what-are-the-pitfalls-of-adl以及std :: tuple和boost :: tuple之間可能存在的接口差異。我知道std :: basic_regex <>也有差異 – sehe

相關問題