What is wrong with my SFINAE to check for std::map/std::vector?

c++, sfinae, std

Solution

You are not using the template `U` in your `test` method:

template <typename Container> struct HasKeyType : sfinae_test { // C
  template <typename U> static Yes test(typename U::key_type* ); // A
  template <typename U> static No test(U*);
  enum {value = (sizeof(test<Container>(0)) == sizeof(Yes))}; // B
};

Note that I changed the `test(null)` for a `test<Container>(0)`. If your compiler supports it(well, gcc 4.5 doesn't...), you could use `nullptr` instead of `0`.

Problem

I have a simple SFINAE scenario to distinuish standard containers like `std::map`: ``` template <typename Container> struct HasKeyType : sfinae_test { // (C) template <typename U> static Yes test(typename Container::key_type*); // (A) template <typename U> static No test(...); enum {value = (sizeof(test(null)) == sizeof(Yes))}; // (B) }; ``` With ``` struct sfinae_test { typedef char Yes; typedef long No; static void* const null; }; ``` When I instantiate this with `HasKeyType<std::vector<int> >::value`, I get ``` (A) error: no type named ‘key_type’ in ‘class std::vector<int>’ (B) error: invalid use of incomplete type ‘struct HasKeyType<std::vector<int> >’ (C) error: declaration of ‘struct HasKeyType<std::vector<int> >’ ``` I'm completely stumped at this. Why is `HasKeyType` incomplete, and why doesn't SFINAE work? I get similar errors to `(B)` and `(C)` as well if I instantiate `HasKeyType<std::map<int,float> >` which in fact has a key type (`int`). g++ version: 4.5.2 (yes, I know it's old)

Original source