Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 304
iammilind Avatar asked Jul 03 '11 15:07

iammilind


1 Answers

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.

like image 110
GManNickG Avatar answered Nov 14 '22 22:11

GManNickG