à l'aide de SFINAE pour la classe template de la spécialisation

supposons que j'ai ces déclarations

template<typename T> class User;
template<typename T> class Data;

et souhaitez mettre en œuvre User<> pour T = Data<some_type> et de toute classe dérivée de Data<some_type> mais aussi d'autres spécialités définies par ailleurs.

Si je n'ai pas encore de la déclaration de la classe de modèle User<>, je pourrais simplement

template<typename T,
         typename A= typename std::enable_if<is_Data<T>::value>::type>
class User { /*...*/ };

template<template<typename> data>> struct is_Data
{ static const bool value = /* some magic here (not the question) */; };

Cependant, ce qui a deux paramètres du modèle et donc des affrontements avec la déclaration précédente, où User<> est déclarée avec un seul paramètre du modèle. Est-il autre chose que je peux faire?

(Note

template<typename T,
         typename A= typename std::enable_if<is_Data<T>::value>::type>
class User<T> { /*...*/ };

ne fonctionne pas (modèle par défaut arguments ne peuvent pas être utilisés dans des spécialisations),
ni ne

template<typename T> class User<Data<T>> { /*...*/ };

qu'il n'autorise pas les types dérivés de Data<>, ni ne

template<typename T>
class User<typename std::enable_if<is_Data<T>::value,T>::type>
{ /*...*/ };

depuis paramètre de modèle T n'est pas utilisé dans la spécialisation partielle.)

  • SFINAE peut être appliqué à choisir le modèle de spécialisations, voir en.cppreference.com/w/cpp/types/enable_if
  • De sorte qu'il peut! J'ai appris quelque chose.
  • Je ne pense pas que je comprends pourquoi les static_assert version ne fonctionnera pas. Soins à élaborer?
  • ce n'était pas un code correct, de toute façon (n'a pas à spécialiser l'original modèle de classe; retiré maintenant).
  • Juste pour clarifier: Vous voulez être en mesure de démarrent des instances User<> pour tout Data<> ou sous-classe, mais pas pour n'importe quel autre type? Devrait User<int> ne parviennent pas à compiler?
  • Oui exactement (à moins que quelqu'un d'autre quelque part déclaré une spécialisation des User<int>).
  • Dans ce cas, pourquoi s'embêter avec une spécialisation partielle à tous? Ne pouvez-vous pas utiliser un statique affirmer dans le commerce non spécialisé version?
  • N je veux avoir d'autres spécialisations partielles, par exemple User<some type dervied from OtherData<0>> (avec template<int> struct OtherData).
  • Le problème est que vous ne pouvez pas changer d'Utilisateur, ou vous êtes à la recherche d'un moyen d'éviter cela. Et si vous êtes à la recherche d'un moyen de l'éviter, mais il est possible de le changer, tant que c'est quelque chose qui n'a pas à casser votre code est-il acceptable?
  • Notez que l'utilisation de std::enable_if pour ce genre de SFINAE est un peu rond-point. À l'aide de typename = std::true_type que la valeur par défaut paramètre, vous pouvez écrire partielle des spécifications qui correspond à <T, typename is_foo<T>::type> en supposant is_foo est par exemple un UnaryTypeTrait dans le sens de la Norme (l'un des traits de <type_traits> comme ça).
  • merci pour cette!

InformationsquelleAutor Walter | 2012-10-12