7
template<typename T>
struct check
{
  static const bool value = false;
};

What I want to do is to have check<T>::value be true if and only if T is a std::map<A,B> or std::unordered_map<A,B> and both A and B be std::string. So basically check enables compile-time checking of the type T. How do I do this?

ildjarn
  • 62,044
  • 9
  • 127
  • 211

2 Answers2

13

Partial specialization for when you want to allow any comparator, hasher, key-equal-comparator and allocator:

template<class Comp, class Alloc>
struct check<std::map<std::string, std::string, Comp, Alloc>>{
  static const bool value = true;
};

template<class Hash, class KeyEq, class Alloc>
struct check<std::unordered_map<std::string, std::string, Hash, KeyEq, Alloc>>{
  static const bool value = true;
};

If you want to check if T used the default version of those types (aka only map<A,B> and not map<A,B,my_comp>, you can omit the template arguments and go with explicit specialization:

template<>
struct check<std::map<std::string, std::string>>{
  static const bool value = true;
};

template<>
struct check<std::unordered_map<std::string, std::string>>{
  static const bool value = true;
};

And if you want to generally check if it's a std::map or std::unordered_map of any key/value combination (and comparator / hasher / etc.), you can go fully generic as taken from here:

#include <type_traits>

template < template <typename...> class Template, typename T >
struct is_specialization_of : std::false_type {};

template < template <typename...> class Template, typename... Args >
struct is_specialization_of< Template, Template<Args...> > : std::true_type {};

template<class A, class B>
struct or_ : std::integral_constant<bool, A::value || B::value>{};

template<class T>
struct check
  : or_<is_specialization_of<std::map, T>,
       is_specialization_of<std::unordered_map, T>>{};
Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
3

Use some partial template specialization

// no type passes the check
template< typename T >
struct check
{
    static const bool value = false;
};

// unless is a map
template< typename Compare, typename Allocator >
struct check< std::map< std::string, std::string, Compare, Allocator > >
{
    static const bool value = true;
};

// or an unordered map
template< typename Hash, typename KeyEqual, typename Allocator >
struct check< std::unordered_map< std::string, std::string, Hash, KeyEqual, Allocator > >
{
    static const bool value = true;
};
K-ballo
  • 80,396
  • 20
  • 159
  • 169