Я хотел бы определить, есть ли у определенного типа член: напрямую и не в результате наследования .
Цель состоит в том, чтобы определить, если специфицирует c тип «имеет черту», такую как возможность сериализации. Естественно, и для расширения примера, подтип может не иметь возможности сериализации, даже если родительский тип имеет.
- Есть ли (и если да) «стандартное» решение этого запроса ?
- Есть ли недостаток (исключая налагаемые им ограничения) в подходе неконвертируемого указателя, представленном внизу?
При использовании is_member_function_pointer
или других механизмов обнаружения наследование в игре. Обратите внимание, что вывод «1», хотя B не определяет член.
#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;
}
Самое близкое, чего я смог достичь, - это использование неконвертируемого указателя (B**
не имеет неявного преобразования до A**
), хотя работать с таким немного неловко. Он также накладывает дополнительный аргумент, соответствующий типу, и предотвращает любое прямое наследование.
#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;
}