我想在前几天编写一个多维地图,偶然发现以下问题。通常,对于地图,您需要key
,cmp
(或less
)和hash
类型。在多维地图中,您需要其中一个用于地图的每个维度。
现在,您如何声明地图类?我尝试了以下方法:
template<typename val, typename ... key, typename ... cmp, typename ... hash>
class multimap;
由于显而易见的原因它没有用,所以我想出了一个解决方法:
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;
虽然这样做有效,但它会强制用户在整个地方重复Dimension<...>
,如果他只想宣布一张简单的地图,那就不幸了!(int, int, int) -> float
看起来像multimap<float, Dimension<int>, Dimension<int>, Dimension<int>>
}。我该怎么做才能让用户更满意?
注意,使用上面的声明,它也使得无法从为每个维度获取Comparator的潜在构造函数推断出特定Dimension的类型。
如何使声明易于使用,例如
multimap<float, int, int, int>
会产生(int, int, int) -> float
mulitmap<float, Dimension<int, some_cmp_t, some_hash_t>, int>
会导致(int, int) -> float
在第一维上使用特殊的比较器和哈希函数。答案 0 :(得分:3)
通过将每个类型传递给辅助特征来将非维度转换为维度:
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>;
};
然后,无论何时引用multimap
的参数包,请使用:
typename DimensionFilter<Dimensions>::type...
您还可以将multimap
设为别名模板,以便其引用的实际类型仅接收Dimensions
:
namespace detail
{
template <typename Val, typename ... Dimensions>
struct multimap {};
}
template <typename Val, typename ... Dimensions>
using multimap = detail::multimap<Val, typename DimensionFilter<Dimensions>::type...>;