I wanted to program a multidimensional map the other day and stumbled over the following problem. Normally, for a map, you need a key
, a cmp
(or less
) and a hash
-type. In a multidimensional map, you'd need one of those for each dimension of the map.
Now, how do you declare the map class? I tried the following:
template<typename val, typename ... key, typename ... cmp, typename ... hash>
class multimap;
For obvious reasons it didn't work so I came up with a workaround:
template<typename Key,
typename Cmp = std::less<Key>,
typename Hash = std::hash<Key>>
struct Dimension
{
using Key = Key;
using Cmp = Cmp;
using Hash = Hash;
};
template<typename Val, typename ... Dimensions>
class multimap;
// Example usage:
multimap<float, Dimension<int>, Dimension<float, some_cmp_t>> my_map;
While this works, it forces the user to repeat Dimension<...>
all over the place, which is unfortunate if he just wanted to declare a simple map, say (int, int, int) -> float
which would look like multimap<float, Dimension<int>, Dimension<int>, Dimension<int>>
. What can I do to make this more pleasing to the user?
Note, with the declaration like above, it also makes it impossible to deduce the type of a specific Dimension from a potential constructor that takes a Comparator for each dimension.
How can I make the declaration easy to use so that eg
multimap<float, int, int, int>
results in (int, int, int) -> float
mulitmap<float, Dimension<int, some_cmp_t, some_hash_t>, int>
results in (int, int) -> float
using a special comparator and hash function on dimension one. Turn non-dimensions into dimensions by passing each type through a helper trait:
template <typename T>
struct DimensionFilter
{
using type = Dimension<T>;
};
template <typename Key, typename Cmp, typename Hash>
struct DimensionFilter<Dimension<Key, Cmp, Hash>>
{
using type = Dimension<Key, Cmp, Hash>;
};
Then whenever you are referring to a parameter pack of multimap
, use:
typename DimensionFilter<Dimensions>::type...
You can also make multimap
an alias template, so that the actual type it refers to already receives only Dimensions
:
namespace detail
{
template <typename Val, typename ... Dimensions>
struct multimap {};
}
template <typename Val, typename ... Dimensions>
using multimap = detail::multimap<Val, typename DimensionFilter<Dimensions>::type...>;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.