I'm trying to implement a map with different access keys using variadic templates in c++. What I want to get is to make such syntax work:
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...
What I have now looks like:
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>
{};
I didn't return iterators in insert and find to make the code simple.
I see two major defects in this solution.
First, the value type goes first in template arguments list. Initially I tried to write
template<class K, class... Krest, class V>
class MultikeyMap<K, Krest..., V>
but compiler insists that "if an argument for a class template partial specialization is a pack expansion it shall be the last argument".
Second is the protected inheritance from std::maps. I would really like to use composition instead of that, but in that case I don't see a way to access the stored maps. If there was a static_if, I would write
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;
};
Please advice on the problems I mentioned. If there is a better approach, I'll be glad to learn.
Thanks for reading.