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.
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>;