iammilind
iammilind

Reputation: 69988

Why SFINAE trick doesn't work for non-class type when tried for class member pointer?

With curiosity, I was trying an alternate implementation of is_class construct using the sizeof() trick. Following is the code:

template<typename T>
struct is_class
{
  typedef char (&yes)[7];
  typedef char (&no)[3];

  static yes check (int T::*);
  static no check (...);

  enum { value = (sizeof(check(0)) == sizeof(yes)) };
};

Problem is when I instantiate is_class<int>, it gives compile error:

error: creating pointer to member of non-class type ‘int’

Now, my question is, if int T::* is not applicable for int (or void* etc.) then why doesn't substitution fail for yes check. Shouldn't compiler select the no check ?

Upvotes: 6

Views: 582

Answers (1)

GManNickG
GManNickG

Reputation: 503913

yes and no are not templates, SFINAE cannot possibly apply to them. You need to do this:

template<typename T>
struct is_class
{
  typedef char (&yes)[7];
  typedef char (&no)[3];

  template <typename U>
  static yes check (int U::*);

  template <typename>
  static no check (...);

  enum { value = (sizeof(check<T>(0)) == sizeof(yes)) };
};

Now SFINAE can kick in.

Upvotes: 10

Related Questions