I want to make a struct that can use any implementation of maps.
Let's call it a MapHolder
. Currently, it looks like this:
template<template<class, class, class...> class MapType>
struct MapHolder
{
MapType<int, int> m_map;
}
And that would work with any map.
But I want to use custom comparator/allocator/hash when possible as well:
// Works only with std::unordered_map
MapType<int, int, my::hash<int>> m_map;
Or
// Works only with std::map
MapType<int, int, std::greater<>> m_map;
And it will compile only with one of the classes.
Can't SFINAE help me to make compiler choose the most appropriate declaration (i.e. first for MapHolder<MyMap>
, second for MapHolder<std::unordered_map>
and so on)?
I would use partial template specialization here. Something as:
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;
}
Live demo: https://godbolt.org/z/mEaFZv.