我正在尝试使用c++中的可变参数模板实现具有不同访问键的 map 。我想要得到的是使这样的语法起作用:
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>
但是编译器坚持“如果类模板局部特化的参数是包扩展,则它应该是最后一个参数” 。
第二个是std::maps的 protected 继承。我真的很想使用合成来代替它,但是在那种情况下,我看不到一种访问存储 map 的方法。如果有一个 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;
};
请就我提到的问题提出建议。如果有更好的方法,我将很高兴学习。
谢谢阅读。
最佳答案
更简单但并非完全等效的方法可能是Boost.Bimap或Boost.MultiIndex。
前者是一个映射,键可以在其中查找值,反之亦然,而后者则更为通用:它是一个具有任意数量索引的容器,允许序列化(“类似列表”),随机访问(“vector 式”),关联性(“ map 式”)和哈希访问。
您可以尝试将Booster.MultiIndex周围的可变参数模板包装起来,然后至少不必重新实现所有的插入/删除逻辑(而只需精简包装器即可)。
注意:Boost.MultiIndex不需要可变的类型序列,您还可以具有可变的成员函数序列,以提取用户定义类的各种数据成员作为主要数据类型。
关于c++ - 使用可变参数模板的多键映射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19153875/