user3059627
user3059627

Reputation: 119

In IsClassT<T>, why use "int C::*"? I am confusing about the int type

An example described in book C++ Templates The Complete Guide:

template <typename T>
class IsClass {
private:
    typedef char One;
    typedef struct { char a[2];} Two;

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

public:
    enum {
        Yes = (sizeof(IsClass<T>::test<T>(0)) == 1)
    };
    enum {
        No = !Yes
    };
};

I've read related topic Where can I find a description about the usage of "int C::*"? I've got the concept that C::* means a pointer to member, and test(0) means test(nullptr), but I have some other questions:

  1. Suppose the compiler does not check if the class C really has a member of type int. Why compiler does not check?
  2. The int type in int C::* could be replaced by any type but void, although I think void is less confusing. Why this error reported?
In file included from testisclass.cpp:12:
../inc/isclass.hpp:17:54: error: cannot declare pointer to ‘void’ member
   17 |         template<typename C> static One test(void C::*);
      |                                                      ^
../inc/isclass.hpp: In instantiation of ‘class IsClass<A>’:
testisclass.cpp:22:16:   required from here
../inc/isclass.hpp:17:41: error: creating pointer to member of type void
   17 |         template<typename C> static One test(void C::*);
      |                                         ^~~~
../inc/isclass.hpp: In instantiation of ‘class IsClass<int>’:
testisclass.cpp:28:18:   required from here
../inc/isclass.hpp:17:41: error: creating pointer to member of type void
  1. Yes = true/false is a complete definition, why still No defined?

Upvotes: 2

Views: 80

Answers (1)

ecatmur
ecatmur

Reputation: 157464

Because the Standard says so. In [dcl.mptr]:

3 - Example: [...]
double X::* pmd;
[...] The declaration of pmd is well-formed even though X has no members of type double. [...]

4 - A pointer to member shall not point to [...] “cvvoid”.

Some possible reasons: if you had to check data members, you wouldn't be able to define pointer to data members of incomplete classes. And while void* is useful for interoperability with C and for type erasure, C doesn't have pointer to member types, and it's unlikely that you'd ever need to type erase a pointer to member.

As for why No is defined in addition to Yes - no idea, perhaps the author thought it might be useful.

Upvotes: 2

Related Questions