使用可变参数模板的多键映射

Gri*_*yan 6 c++ templates variadic variadic-templates c++11

我正在尝试使用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...
Run Code Online (Sandbox Code Playgroud)

我现在看起来像:

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

我没有在insert中返回迭代器,并且发现使代码变得简单.

我看到这个解决方案有两个主要缺陷.

首先,值类型在模板参数列表中排在第一位.最初我试着写

template<class K, class... Krest, class V>
class MultikeyMap<K, Krest..., V>
Run Code Online (Sandbox Code Playgroud)

但是编译器坚持认为"如果类模板部分特化的参数是包扩展,它应该是最后一个参数".

第二个是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;
};
Run Code Online (Sandbox Code Playgroud)

请就我提到的问题提出建议.如果有更好的方法,我会很高兴学习.

谢谢阅读.

Tem*_*Rex 2

更简单但不完全等效的方法可能是Boost.BimapBoost.MultiIndex

前者是一个映射,其中键可以在其中查找值,反之亦然,而后者则更为通用:它是一个具有任意数量索引的容器,允许排序(“类似列表”)、随机访问(“矢量式”)、关联式(“地图式”)和散列访问。

您可以尝试将可变参数模板包装在 Boost.MultiIndex 周围,那么至少您不必重新实现所有插入/擦除逻辑(但仅是薄包装器)。

注意:Boost.MultiIndex 不需要类型的可变序列,您还可以使用成员函数的可变序列来提取用户定义类的各种数据成员作为主要数据类型。