Vinod
Vinod

Reputation: 1081

Question on how SFINAE is achieved using this code segment

With reference to

SFINAE

the question relates to the following code segment:

template<typename T>
class is_class {
    typedef char yes[1];
    typedef char no [2];
    template<typename C> static yes& test(int C::*); // selected if C is a class type
    template<typename C> static no&  test(...);      // selected otherwise
  public:
    static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};

In the above class template definition, the public definition for is_class<T>::value instantiates the nested static template function test using the parameter T used in the instantiation of the class template is_class.

If the above interpretation is correct, I have the following questions:

  1. How does one interpret the overloaded versions of the the nested static template function test?

How does SFINAE work using the above overloads to populate the public boolean variable value of template class is_class<T> for a given T, with true or false as applicable, based on sizeof(test<T>(0)) == sizeof(yes)? I am not sure I understand how passing what appears to be a random integer value 0 in the instantiation of test<T> should either choose or eliminate either overload? Can someone provide an explanation with an example?

  1. The logic of using two nested types of yes[1] and no [2], both of which have been typedef'd to char is also not clear to me. Assuming that yes[1] is a type alias for a char array with size 1, and no[2] a type alias for a char array with size 2, how does this logic integrate into the overload selection/elimination using SFINAE?

Appreciate your thoughts.

Upvotes: 0

Views: 54

Answers (1)

R Sahu
R Sahu

Reputation: 206607

Let's clear some misunderstandings:

  1. yes[1] is not a type. yes is a type, and it is an alias for char [1].
  2. no[2] is not a type. no is a type, and it is an alias for char [2].

When it comes to overload resolution, test(...) is given lower priority if T is a class. Hence, the call test<T>(0) will resolve to the first overload, whose return type is yes&. Consequently,

sizeof(test<T>(0)) == sizeof(yes) evaluates to
sizeof(yes) == sizeof(yes), which evaluates to true.

If T is not a class, there is no int T::*. That's the SFINAE part. For that case, test(...) is chosen as the overload, whose return type is no&. Hence,

sizeof(test<T>(0)) == sizeof(yes) evaluates to
sizeof(no) == sizeof(yes), which evaluates to false.

Upvotes: 1

Related Questions