我想定义std::tr1::hash<boost::tuple<A,B,C> >
。但是当我给出一个完整的瞬间时,我得到的错误并没有出现。这是代码
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 :(得分: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
的类型取决于三个模板参数(因此t
依赖于类型),get<0>
是模板特化的名称。从C ++标准 - §14.2/4
:
当成员模板专业化的名称出现之后。或 - &gt;在postfix-expression ...中,postfix-expression的对象表达式依赖于类型...成员模板名称必须以关键字模板为前缀。 ...
此要求允许在知道类型参数之前解析模板。
例如,考虑:
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
应该是空的()
。
答案 1 :(得分:6)
我没有时间检查,但我希望
std::get<0>(t)
或
boost::get<0>(t)
而不是t.get<0>()
限定 get()即使您正在“使用”命名空间,或者在混合这样的库时ADL会对您造成严重伤害。见What are the pitfalls of ADL?