0

Reading other topic here I've already wrote code detecting if class is associative container[1]. Right now in order to use equal_range I need to detect if it's normal map or multimap. Is there any way I can achieve my goal?

Piwniczne
  • 11
  • 4

3 Answers3

3

You might probably add your own type trait:

template<typename>
struct is_map : std::false_type {};

template<typename K, typename V>
struct is_map<std::map<K, V>> : std::true_type {};

WANDBOX example

Edgar Rokjān
  • 16,412
  • 4
  • 37
  • 63
  • Sadly, this does not work if you try to detect a type that inherits from a map. For example: struct MyMap : public std::map{}; is_map will fail to match the true instantiation. I'll report back if I find a solution, as that's what I need in my own code base. – Jonathan O'Connor Jun 15 '20 at 18:49
0

You could also use the suggestions in this post to specialise based on the existence of at() or operator[]

IlBeldus
  • 996
  • 5
  • 14
0

The original answer works perfectly well for checking if a type is a map or not. However, it doesn't work for testing if a type inherits from a map. I made various attempts at a general solution and finally I came up with the following code:

namespace details {
    constexpr bool is_map(const void*) {
        return false;
    }

    template<typename K, typename V, typename Comp, typename Alloc>
    constexpr bool is_map(const std::map<K, V, Comp, Alloc>*) {
        return true;
    }
}

template<typename T>
constexpr bool is_map_v = details::is_map(static_cast<const T*>(nullptr));

using map1 = std::map<int, int>;
static_assert(is_map_v<map1>);

struct MyMap : public std::map<int, int>{};
static_assert(is_map_v<MyMap>);

static_assert(is_map_v<int> == false);

It has 2 overloads for the is_map function. One matches pointers to maps, and the other matches everything else. Because they take pointers, passing the address of something publicly derived from map will also be accepted.

The is_map(const void *) will only match if T can't possibly be a map.