在tr1 :: hash中使用boost :: tuple

pyt*_*hor 8 c++ templates

我想定义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;
    }
};
}
}
Run Code Online (Sandbox Code Playgroud)

第一部分给出了这个错误

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
Run Code Online (Sandbox Code Playgroud)

第二个编译得很好.第一个模板出了什么问题?我正在使用gcc 4.3.4.

Man*_*rse 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;
    }
};
Run Code Online (Sandbox Code Playgroud)

这是必需的,因为类型t取决于三个模板参数(因此t是类型相关的),并且get<0>是模板特化的名称.从C++标准 - §14.2/4:

当成员模板专业化的名称出现之后.或 - >在postfix-expression ...中,postfix-expression的对象表达式依赖于类型...成员模板名称必须以关键字模板为前缀....

存在此要求以允许在其类型参数已知之前解析模板.

例如,考虑:

f . set < 0 > ( 2 == 3 )
Run Code Online (Sandbox Code Playgroud)

没有.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)
Run Code Online (Sandbox Code Playgroud)

实际规则允许f . set < 0 > ( 2 == 3 )明确地解析为一系列比较操作.它们也意味着t.get<0>()被解析为t.get < 0 > ().这expected primary-expression意味着空虚().


seh*_*ehe 6

我没有时间检查事情,但我也指望

std::get<0>(t)
Run Code Online (Sandbox Code Playgroud)

要么

boost::get<0>(t)
Run Code Online (Sandbox Code Playgroud)

代替 t.get<0>()

有资格的get(),即使你是"用"的命名空间,或混合类似这样的库时,ADL会严重伤害你.看看ADL的缺陷是什么?