44 votes

Pourquoi la spécialisation partielle d'un modèle de classe imbriquée est-elle autorisée, alors que complète n'est pas?

    template<int x> struct A {                                                                                                    
        template<int y> struct B {};.                                                                                             
        template<int y, int unused> struct C {};                                                                                  
    };                                                                                                                            

    template<int x> template<> 
    struct A<x>::B<x> {}; // error: enclosing class templates are not explicitly specialized

    template<int x> template<int unused> 
    struct A<x>::C<x, unused> {}; // ok

Alors, pourquoi est explicite spécialisation d'un intérieur, classe imbriquée (ou une fonction) non autorisé, si l'extérieur de la classe n'est pas spécialisées trop? Assez étrange, je peux contourner ce comportement, si j'ai seulement partiellement spécialiser l'intérieur de la classe avec simplement l'ajout d'un mannequin paramètre du modèle. Rend les choses plus laide et la plus complexe, mais il fonctionne.

Je considère complète des spécialisations comme un sous-ensemble de spécialisations partielles - en particulier parce que vous pouvez exprimer toutes une spécialisation totale partielle avec l'ajout d'un paramètre fictif. Donc, cette homonymie entre partielles ou totales de la spécialisation n'a pas vraiment de sens pour moi.

Malheureusement, la personne à la comp.std.c++ osé répondre, alors je suis le mettre en place ici à nouveau avec un bounty.

Note: j'ai besoin de cette fonctionnalité pour les modèles de l'intérieur de la classe pour un jeu de l'extérieur de la classe et de la spécialisation de l'intérieur de paramètre ne dépend pas de l'extérieur paramètre du modèle.

30voto

Virgil Points 1693

J'imagine pourquoi cela se produit: les spécialisations complètes ne sont plus des "classes / fonctions de gabarit", mais des "vraies" classes / méthodes, et ont ainsi la possibilité d'avoir de vrais symboles (visibles par l'éditeur de liens). Mais pour un modèle complètement spécialisé dans un modèle partiellement spécialisé, cela ne serait pas vrai. Cette décision a probablement été prise simplement pour simplifier la vie des rédacteurs de compilateurs (et rendre la vie plus difficile pour les codeurs, dans le processus: P).

8voto

Kirill V. Lyadvinsky Points 47627

Norme C++ interdit explicitement plein de spécialisation des membres de classes de modèle dans le premier cas. Selon l'article 14.7.3/18:

Explicite de la spécialisation de la déclaration d'un membre d'un modèle de classe ou un membre de modèle qui s'affiche dans l'espace de noms de la portée, le membre de modèle et de certains de ses enfermant modèles de classe peuvent rester non spécialisé, sauf que la déclaration ne doit pas explicitement spécialiser un membre de la classe du modèle si sa classe englobante les modèles ne sont pas explicitement spécialisées ainsi.

7voto

Matthieu M. Points 101624

Vous pouvez contourner ce problème en déléguant le travail réel à une autre structure:

 namespace detail
{
  template <class T, class U>
  struct InnerImpl {};
}

template <class T>
struct Outer
{
  template <class U>
  struct Inner: detail::InnerImpl<T,U>
  {
  };
};
 

Maintenant, vous pouvez vous spécialiser InnerImpl comme vous le souhaitez

4voto

Joris Timmermans Points 8075

La sauvegarde de Virgile argument (il a été plus rapide que j'ai poster le même raisonnement), pensez à ceci:

template<typename T1>
class TOuter
  {
  public:
    template<typename T2>
    class TInner
      {
      public:
        T1 m_1;
        T2 m_2;
      };
  };

template<typename T1>
template<>
class TOuter<T1>::TInner<float>
  {
  public:
    T1    m_1;
    float m_2;
 };

Est TInner entièrement spécialisée, ou partiellement spécialisés en raison de T1?

Edit:

Après avoir tenu compte de certains des autres commentaires, il semblerait que vous voulez avoir plein de spécialisation basée sur le paramètre de modèle à l'extérieur de la classe. Si vous nid à l'intérieur de la classe de mise en œuvre, qui semble fonctionner dans Visual Studio 2005:

template<typename T1>
class TOuter
  {
  public:
    template<typename T2>
    class TInner
      {
      public:
        std::string DoSomething() { return "Inner - general"; }
        T2 m_2;
      };

    template<>
    class TInner<T1>
      {
      public:
        std::string DoSomething() { return "Inner - special"; }
        T1 m_1;
      };
  };

TOuter::TInner sera bien de la spécialisation des TInner. Je ne pourrais pas obtenir de compiler avec la mise en œuvre à l'extérieur du modèle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X