IsClassT<T>中为什么要用"int C::*"?我对 int 类型感到困惑

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

C++ 模板完整指南 中描述的示例:

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
    };
};

我已阅读相关主题Where can I find a description about the usage of "int C::*"? 我的概念是 C::* 表示指向成员的指针,而 test(0) 表示 test(nullptr),但我还有其他问题:

  1. 假设编译器不检查 class C 是否真的有 int 类型的成员。为什么编译器不检查?
  2. int 类型 int C::* 可以替换为任何类型,但 void,尽管我认为 void 不那么令人困惑。为什么报这个错误?
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. =true/false定义完整,为什么还是没有定义?

因为标准是这么说的。在 [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”.

一些可能的原因:如果你必须检查数据成员,你将无法定义指向不完整数据成员的指针类。虽然 void* 对于与 C 的互操作性和类型擦除很有用,但 C 没有指向成员类型的指针,而且您不太可能需要类型擦除指向成员的指针。

至于为什么在 Yes 之外还定义了 No - 不知道,也许作者认为它可能有用。