0

In C++17, I'm trying to detect containers (maps) by checking for the presence of value_type (mapped_type). However, while it seems to work for unordered_set<int> it fails for unordered_set<int*> which I find weird. Can you tell me why and how to do it properly?

  template<class N, class T = int>
  struct is_container { static const bool value = false; };
  template<class N>
  struct is_container<N, typename N::value_type> { static const bool value = true; };
  template<class N>
  static constexpr bool is_container_v = is_container<remove_reference_t<N>>::value;


int main()
{
  cout << is_container_v<unordered_set<int>&> << '\n';
  cout << is_container_v<unordered_set<int*>&> << '\n';
}

output:

1
0

PS: I've seen this question which filters by presence of begin() but that doesn't help telling a map from set.

igel
  • 358
  • 1
  • 8

1 Answers1

3

Keeping your test, it should be

template<class N, class Enabler = void>
struct is_container { static const bool value = false; };

template<class N>
struct is_container<N, std::void_t<typename N::value_type>>
{ static const bool value = true; };

template<class N>
static constexpr bool is_container_v = is_container<remove_reference_t<N>>::value;

As, with your version

is_container_v<unordered_set<int*>&> is is_container<unordered_set<int*>> and with default: is_container<unordered_set<int*>, int>

whereas you specialize for is_container<unordered_set<int*>, int*>...

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • ah, thanks for the explanation, that makes perfect sense now. I had a misunderstanding about specializations... – igel Apr 06 '20 at 15:52