Я пытаюсь определить, имеет ли класс определенную функцию (в частности shared_from_this()
, которая унаследована от std::enable_shared_from_this<Some Unknown Class>
). Чтобы усложнить ситуацию, мне нужно знать, имеет ли она эту функцию, даже если она унаследована от удаленного базового класса или унаследована с использованием защищенного доступа.
Я рассмотрел другие вопросы, такие как этот, но предоставленные методы не работают для обнаружения защищенных функций-членов.
Текущий метод, который я использую, следующий:
template <class T>
struct shared_from_this_wrapper : public T
{
template <class U>
static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
};
template<class T>
struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>()))
{ };
Недостатком моего текущего решения является то, что он не работает с объявленными классами final
. Поэтому я получаю решение для тестирования функции-члена, которая удовлетворяет:
- Работа с объявленными классами
final
- Работает с защищенными функциями-членами
- Работает с наследованием
- Не нужно знать возвращаемый тип функции
- Компиляция под gcc, clang и MSVC 2013 (последняя, потенциально ограничивающая чрезмерно причудливую SFINAE)
Изменить: у меня есть потенциальное решение, которое работает, но требует подружиться со вспомогательным классом, который также не является идеальным решением, но, возможно, обходным путем (поскольку он удовлетворяет всем требованиям):
struct access
{
template <class T>
static auto shared_from_this( T const & t ) -> decltype( t.shared_from_this() );
};
template <class U>
static auto check( U const & t ) -> decltype( access::shared_from_this(t), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
template<class T>
struct has_shared_from_this2 : decltype(check(std::declval<T>()))
{ };
struct A : std::enable_shared_from_this<A> {};
struct B : protected A { friend class access; };
Другое редактирование: примеры классов и то, что должен проверять наличие признаков типа shared_from_this
:
struct A : std::enable_shared_from_this<A> {}; // should return true
struct B final : protected A {}; // should return true
struct C : A {}; // should return true
struct D {}; // should return false
Я должен упомянуть, что моя конечная цель в определении того, существует ли эта функция, заключается в том, чтобы определить возвращаемый тип, чтобы выяснить тип, на котором был template шаблоном std::enable_shared_from_this
. Наследование от std::enable_shared_from_this<T>
дает вам std::shared_ptr<T> shared_from_this()
, а T
- это в конечном счете то, что мне нужно выяснить. Это необходимо для правильной сериализации типов, которые наследуются от std::enable_shared_from_this
.
Изменить часть 3: Редактирование:
Это делается для библиотеки сериализации cereal, и поэтому у меня есть нулевой контроль над тем, как пользователь хочет создать свой класс, Я хотел бы иметь возможность сериализовать любой тип пользователя, полученный из std::enable_shared_from_this
, который включает пользователей, которые объявляют свои классы как окончательные, или используют защищенное наследование где-то на этом пути. Любое решение, которое требует вмешательства с проверяемым фактическим типом, не является допустимым решением.