Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where can I find a description about the usage of "int C::*"?

Tags:

c++

stl

In a piece of code, I find something as :

template<typename T>
class IsClassT {
  private:
    typedef char One;
    template<typename C> static One test(int C::*);
...

The question is where can I find a description about why the usage of "int C::*" is valid in function test() definition?

like image 884
Huang F. Lei Avatar asked Jul 31 '11 15:07

Huang F. Lei


3 Answers

int C::* is a pointer to a member of C of type int. Search for "pointer-to-member". The section of the standard (ISO/IEC 14882:2003) that deals with this declaration syntax is 8.3.3 Pointers to members [dcl.mptr].

Example usage.

struct Example
{
    int a;
    int b;
};

int test( Example& ex, int Example::* p )
{
    return ex.*p;
}

int main()
{
    Example x = { 3, 5 };
    // Convoluted way of extracting x.a and x.b
    int a = test( x, &Example::a );
    int b = test( x, &Example::b );
}
like image 109
CB Bailey Avatar answered Nov 28 '22 09:11

CB Bailey


I won't describe what int C::* means since @Charles Bailey already did that very well. I will however answer your question:

(...) why the usage of "int C::*" is valid in function test() definition?

The key point is that the usage of int C::* (pointer to member of type int) is valid if and only if C is a class type. Otherwise the type int C::* is ill-formed.

This is why you have

template<typename C> static One test(int C::*);

and most probably somewhere below

template <typename> static Two test(...);
static const bool value = sizeof(test<T>(0)) == 1;

When test<T>(0) is seen by the compiler, it examines the candidates for test. It finds two:

template<typename C> static One test(int C::*);   
template <typename> static Two test(...);

The first has precedence over the second because 1) they are both template functions and 2) the ellipsis is looked up last. If the first one is ill formed (ie. if and only if C is not a class type), then it is simply discarded and the second overload is taken. This behaviour is nicknamed SFINAE (for Substitution Failure Is Not An Error).

Testing for the size of the return type (remember that sizeof(char) is always 1), you can assess at compile time which test is taken, ie. whether T is a class type or not.

like image 37
Alexandre C. Avatar answered Nov 28 '22 09:11

Alexandre C.


It is a pointer to member.
A simple example to understand Pointer to member.

class A
{
   int a;
   int b;
   void DoSomething();
};

int main()
{
   A *ObjPtr;

   //pointer to member a
   int A::*ptr = &A::a;    

   //Usage
   objPtr->*ptr = NULL;

   //pointer to member function
   void (A::*FuncPtr)(void) = &A::DoSomething; 

   //Usage
   (objPtr->*FuncPtr)(void);    

   return 0;
}
like image 39
Alok Save Avatar answered Nov 28 '22 09:11

Alok Save