Je tente de détecter si une classe possède une fonction particulière (spécifiquement shared_from_this()
, qui est héritée de std::enable_shared_from_this
). Pour compliquer les choses, je dois savoir si cette fonction existe même si elle a été héritée d'une classe de base lointaine ou héritée en utilisant un accès protégé.
J'ai regardé d'autres questions telles que celle-ci, mais les méthodes proposées ne fonctionnent pas pour détecter les fonctions membres protégées.
La méthode actuelle que j'utilise est la suivante :
template
struct shared_from_this_wrapper : public T
{
template
static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
};
template
struct has_shared_from_this : decltype(shared_from_this_wrapper::check(std::declval>()))
{ };
Le défaut de ma solution actuelle est qu'elle ne fonctionne pas avec des classes déclarées final
. Je suis donc à la recherche d'une solution pour tester une fonction membre qui satisfait :
- Fonctionne avec des classes déclarées
final
- Fonctionne avec des fonctions membres protégées
- Fonctionne avec l'héritage
- N'a pas besoin de connaître le type de retour de la fonction
- Compile sous gcc, clang et MSVC 2013 (ce dernier limitant éventuellement une SFINAE trop sophistiquée)
Édit : J'ai une solution potentielle qui fonctionne mais qui nécessite de rendre ami une classe auxiliaire, ce qui n'est pas non plus une solution idéale mais peut être une solution de contournement pour le moment (car elle satisfait toutes les exigences) :
struct access
{
template
static auto shared_from_this( T const & t ) -> decltype( t.shared_from_this() );
};
template
static auto check( U const & t ) -> decltype( access::shared_from_this(t), std::true_type() );
static auto check( ... ) -> decltype( std::false_type() );
template
struct has_shared_from_this2 : decltype(check(std::declval()))
{ };
struct A : std::enable_shared_from_this {};
struct B : protected A { friend class access; };
Un autre édit : exemples de classes et ce qu'un type doit renvoyer en vérifiant l'existence de quelque chose comme shared_from_this
:
struct A : std::enable_shared_from_this
{}; // devrait renvoyer vrai struct B final : protected A {}; // devrait renvoyer vrai struct C : A {}; // devrait renvoyer vrai struct D {}; // devrait renvoyer faux
Je devrais mentionner que mon objectif final en détectant si cette fonction existe est de déterminer le type de retour de celle-ci afin de comprendre le type sur lequel std::enable_shared_from_this
a été instancié. Hériter de std::enable_shared_from_this
vous donne std::shared_ptr shared_from_this()
, et T
est finalement ce que j'ai besoin de comprendre. Cela est nécessaire pour une sérialisation correcte des types qui héritent de std::enable_shared_from_this
.
Édit partie 3 : La modification :
Cela est fait pour la bibliothèque de sérialisation cereal et en tant que tel, je n'ai aucun contrôle sur la manière dont un utilisateur souhaite concevoir sa classe. Je voudrais pouvoir sérialiser n'importe quel type d'utilisateur qui dérive de std::enable_shared_from_this
, ce qui inclut les utilisateurs qui déclarent leurs classes comme final ou utilisent l'héritage protégé quelque part dans le processus. Toute solution qui nécessite de manipuler le type réel qui est vérifié n'est pas une solution valide.