I would like to detect if a particular type has a member: directly and not as a result of inheritance.
The purpose is to determine if a specific type 'has a trait' such as the ability to serialize. Naturally, and for extending the example, a sub-type might not have the ability to serialize even if the parent type does.
- Is there (and if so) a "standard" solution to this request?
- Is there a flaw (excluding the limitations it imposes) with the non-convertible pointer approach presented at the bottom?
When using is_member_function_pointer
or other detection mechanisms, inheritance is in play. Note that the output is "1" even though B does not define the member.
#include <type_traits>
#include <iostream>
struct A {
void member() { }
};
struct B : A {
};
int main()
{
std::cout << "B has member? "
<< std::is_member_function_pointer<decltype(&B::member)>::value
<< std::endl;
}
The closest I have been able to achieve is when using a non-convertible pointer (B**
has no implicit conversion to A**
), although such is a bit awkward to work with. It also imposes the additional argument matched to the type and prevents any direct inheritance.
#include <type_traits>
#include <iostream>
struct A {
// would match std::declval<B*> as B* -> A*,
// hence forcing failure through B** -> A**.
// void member(A*) { }
void member(A**) { }
};
struct B : A {
// succeeds compilation aka "found" if not commented
// void member(B**) { }
};
int main()
{
// This actually fails to compile, which is OKAY because it
// WORKS when used with SFINAE during the actual detection.
// This is just a simple example to run.
// error: invalid conversion from 'B**' to 'A**'
std::cout << "B has member? "
<< std::is_member_function_pointer<
decltype(std::declval<B>().member(std::declval<B**>()))
>::value
<< std::endl;
}