Reputation: 119
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:
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
Upvotes: 2
Views: 80
Reputation: 157464
Because the Standard says so. In [dcl.mptr]:
3 - Example: [...]
double X::* pmd;
[...] The declaration ofpmd
is well-formed even thoughX
has no members of typedouble
. [...]4 - A pointer to member shall not point to [...] “
cv
void
”.
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