前几天我想编写一个多维 map ,并偶然发现了以下问题。通常,对于 map ,您需要 key
,一个cmp
(或 less
)和 hash
-类型。在多维 map 中,您需要为 map 的每个维度提供其中一个。
现在,如何声明 map 类?我尝试了以下方法:
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<...>
到处都是,如果他只是想声明一个简单的 map ,比如(int, int, int) -> float
,那就很不幸了看起来像 multimap<float, Dimension<int>, Dimension<int>, Dimension<int>>
。我该怎么做才能让用户更满意?
请注意,使用上面的声明,也无法从为每个维度采用 Comparator 的潜在构造函数中推断出特定维度的类型。
如何使声明易于使用,例如
-
multimap<float, int, int, int>
结果(int, int, int) -> float
-
mulitmap<float, Dimension<int, some_cmp_t, some_hash_t>, int>
结果(int, int) -> float
在第一维上使用特殊的比较器和哈希函数。
最佳答案
通过将每种类型传递给辅助特征,将非维度转换为维度:
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...>;
关于c++ - 可变默认参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33042166/