web-dev-qa-db-fra.com

Implémenter un trait de type pour un modèle de classe qui est vrai pour le modèle de classe actuel et les classes qui l'héritent

J'ai un modèle de classe de type tuple comme celui-ci

template <class... T>
struct Foo {}

Maintenant, j'ai besoin de mettre en œuvre quelque chose comme ça

template <class T>
void bar (const T& t)
{
    if constexpr (IsFoo<T>::value)
        // treat it as Foo
    else
        // a generic solution
}

IsFoo peut être mis en œuvre directement comme celui-ci

template <class T>
struct IsFoo : std::false_type {}

template <class... T>
struct IsFoo<Foo<T...>> : std::true_type {}

Maintenant, j'ai aussi besoin de IsFoo pour être vrai au cas où le type adopté est dérivé publiquement de toute instanciation de Foo, par exemple.

struct Derived : public Foo<int, float> {}

devrait également être traité comme un Foo dans le premier if constexpr branche ci-dessus.

Cependant, je ne peux pas comprendre comment implémenter correctement une spécialisation de matrice de mon IsFoo trait qui fonctionnerait lorsque Derived est transmis à cela. Mais je suis sûr que Stackoverflow sait comment!

Edit: J'ai découvert que bien que tous les compilateurs utilisés pour les concepts de support de projet, bien qu'il n'y ait pas de support complet C++ 20. J'ai donc décidé de pouvoir utiliser les solutions conceptuelles proposées.

3
PluginPenguin

Ma version avec C++ 14 (peut être modifiée à C++ 11 facilement):

template <template<typename...> typename T, class... U>
void callWithTemplateBase(const T<U...>&);

template <typename T, template<typename...> typename Base, typename U = void>
struct IsInstanceOfTemplate : std::false_type {};

template <typename T, template<typename...> typename Base>
struct IsInstanceOfTemplate<
        T, 
        Base, 
        decltype(callWithTemplateBase<Base>(std::declval<T>()))> 
    : std::true_type {};

template <typename T, template<typename...> typename Base>
constexpr bool IsInstanceOfTemplate_v = IsInstanceOfTemplate<T, Base>::value;


template <class... T>
struct Foo {};

template<typename T>
constexpr bool IsFoo_v = IsInstanceOfTemplate_v<T, Foo>;

https://godbolt.org/z/sv7jtpbe6

0
Marek R