在tr1::hash中使用boost::元组

Using boost::tuple in tr1::hash

本文关键字:boost 元组 tr1 hash      更新时间:2023-10-16

我想定义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

和第二个可以很好地编译。第一个模板有什么问题?

您需要使用.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:

成员模板特化的名称出现在。或->在后缀表达式…而后缀表达式的对象表达式是类型依赖的…成员模板名称必须以关键字template. ...

作为前缀。

此要求允许在模板的类型参数已知之前对其进行解析。

例如:

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应该在空的()

我没有时间检查,但我希望

std::get<0>(t)

boost::get<0>(t)

代替t.get<0>()

Do qualified get(),即使你正在"使用"命名空间,否则ADL会在像这样混合库时严重伤害你。参见ADL的陷阱是什么?