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?
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 );
}
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.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With