【发布时间】:2013-10-09 20:06:10
【问题描述】:
我正在尝试使用 C++ 中的可变参数模板实现具有不同访问键的映射。我想要的是使这样的语法工作:
MultikeyMap<int, double, float> map1; // int and double are keys, float is value type
map1[ 2 ] = 3.5;
map1[ 5.7 ] = 22;
MultikeyMap<unsigned long long, int, float, double, int> map2; // more keys, int is value type
map2[100000000000ULL] = 56;
// etc...
我现在的样子:
template<class V, class... Krest>
class MultikeyMap;
template<class V, class K, class... Krest>
class MultikeyMap<V, K, Krest...> : protected std::map<K, V>,
protected MultikeyMap<V, Krest...>
{
public:
template<class T>
void insert( const T& t, const V& v )
{
std::map<T, V>::insert( make_pair( t, v ));
}
template<class T>
const V* find( const T& k )
{
typedef std::map<T,V> currentMap;
currentMap::const_iterator it = currentMap::find( k );
return it == currentMap::end() ? 0 : &it->second;
}
};
template<class V>
class MultikeyMap<V>
{};
我没有在 insert 和 find 中返回迭代器以简化代码。
我发现这个解决方案有两个主要缺陷。
首先,值类型在模板参数列表中排在第一位。最初我试图写
template<class K, class... Krest, class V>
class MultikeyMap<K, Krest..., V>
但编译器坚持“如果类模板部分特化的参数是包扩展,它应该是最后一个参数”。
Second 是来自 std::maps 的受保护继承。我真的很想使用合成来代替,但在这种情况下,我看不到访问存储地图的方法。如果有 static_if,我会写
template<class V, class K, class... Krest>
class MultikeyMap<V, K, Krest...> : protected MultikeyMap<V, Krest...>
{
public:
template<class T>
void insert( const T& t, const V& v )
{
static if( is_same<T,K>::value )
m_map.insert( make_pair( t, v ));
else
MultikeyMap<V, Krest...>::insert( t, v );
}
private:
std::map<K,V> m_map;
};
请就我提到的问题提出建议。如果有更好的方法,我会很高兴学习。
感谢阅读。
【问题讨论】:
-
MultikeyMap<unsigned long long, int, int, double, int>:int被两次引用为关键,这是真的吗?你怎么知道用户是在看第一个还是第二个int?另外,我不清楚您要达到什么目的;一个值应该同时出现在所有地图中吗?因为如果它只是在一张地图中,那么拥有一个大的公共容器是没有意义的。 -
@MatthieuM.:谢谢你的观点,应该有一个 int。该值现在应该存在于一个映射中,但稍后我将添加一个功能,为已存储的值添加另一个键。
标签: c++ templates c++11 variadic-templates variadic