如何使用 SFINAE 区分 MyMap、std::map 和 std::unordered_map?
How can I use SFINAE to distinguish MyMap, std::map and std::unordered_map?
我想制作一个可以使用任何映射实现的结构。
我们称它为 MapHolder
。目前,它看起来像这样:
template<template<class, class, class...> class MapType>
struct MapHolder
{
MapType<int, int> m_map;
}
这适用于任何地图。
但我也想尽可能使用自定义 comparator/allocator/hash:
// Works only with std::unordered_map
MapType<int, int, my::hash<int>> m_map;
或
// Works only with std::map
MapType<int, int, std::greater<>> m_map;
而且它只会用类之一编译。
SFINAE 不能帮我让编译器选择最合适的声明吗(即第一个用于 MapHolder<MyMap>
,第二个用于 MapHolder<std::unordered_map>
等等)?
我会在这里使用部分模板专业化。如:
template<template<class, class, class...> class MapType>
struct MapHolder
{
private:
template <typename> struct ThirdArgument;
template <typename K, typename V, typename C, typename A>
struct ThirdArgument<std::map<K, V, C, A>>
{
using type = std::greater<K>;
};
template <typename K, typename V, typename H, typename E, typename A>
struct ThirdArgument<std::unordered_map<K, V, H, E, A>>
{
using type = std::hash<K>;
};
public:
MapType<int, int,
typename ThirdArgument<MapType<int, int>>::type
> m_map;
};
int main()
{
MapHolder<std::map> m1;
MapHolder<std::unordered_map> m2;
}
我想制作一个可以使用任何映射实现的结构。
我们称它为 MapHolder
。目前,它看起来像这样:
template<template<class, class, class...> class MapType>
struct MapHolder
{
MapType<int, int> m_map;
}
这适用于任何地图。
但我也想尽可能使用自定义 comparator/allocator/hash:
// Works only with std::unordered_map
MapType<int, int, my::hash<int>> m_map;
或
// Works only with std::map
MapType<int, int, std::greater<>> m_map;
而且它只会用类之一编译。
SFINAE 不能帮我让编译器选择最合适的声明吗(即第一个用于 MapHolder<MyMap>
,第二个用于 MapHolder<std::unordered_map>
等等)?
我会在这里使用部分模板专业化。如:
template<template<class, class, class...> class MapType>
struct MapHolder
{
private:
template <typename> struct ThirdArgument;
template <typename K, typename V, typename C, typename A>
struct ThirdArgument<std::map<K, V, C, A>>
{
using type = std::greater<K>;
};
template <typename K, typename V, typename H, typename E, typename A>
struct ThirdArgument<std::unordered_map<K, V, H, E, A>>
{
using type = std::hash<K>;
};
public:
MapType<int, int,
typename ThirdArgument<MapType<int, int>>::type
> m_map;
};
int main()
{
MapHolder<std::map> m1;
MapHolder<std::unordered_map> m2;
}