123 votes

Explicite spécialisation dans le non-espace de noms portée

template<typename T>
class CConstraint
{
public:
    CConstraint()
    {
    }

    virtual ~CConstraint()
    {
    }

    template <typename TL>
    void Verify(int position, int constraints[])
    {       
    }

    template <>
    void Verify<int>(int, int[])
    {   
    }
};

La compilation de ce sous g++ donne l'erreur suivante:

Explicite spécialisation dans le non-espace de noms de champ d'application "de la classe CConstraint'

Dans VC, il compile bien. Quelqu'un peut s'il vous plaît laissez-moi savoir la solution de contournement?

95voto

Georg Fritzsche Points 59185

VC++ est ne respectant pas dans ce cas - explicite spécialisations doivent être à portée espace de noms. C++03, §l'article 14.7.3/2:

Explicite de spécialisation doivent être déclarés dans l'espace de noms dont le modèle est membre, ou, pour les modèles de membre, dans l'espace de noms dont la classe englobante ou de la classe englobante modèle est membre.
Explicite de la spécialisation d'une fonction membre, membre de la classe ou de la donnée membre statique d'une classe de modèle doivent être déclarés dans l'espace de noms dont le modèle de classe est un membre.

En outre, vous avez le problème que vous ne pouvez pas se spécialisent fonctions de membre sans explicitement spécialisée le contenant de la classe, donc une seule solution serait de laisser Verify() de l'avant à un, éventuellement spécialisés, gratuit fonction:

namespace detail {
    template <typename TL> void Verify     (int, int[]) {}
    template <>            void Verify<int>(int, int[]) {}
}

template<typename T> class CConstraint {
    // ...
    template <typename TL> void Verify(int position, int constraints[]) {
        detail::Verify<TL>(position, constraints);
    }
};

89voto

Une autre façon de le résoudre est de déléguer à une fonction privée et de surcharger cette fonction. De cette façon, vous avez toujours accès à des données sur les membres de l' *this et à l'extérieur du modèle type de paramètre.

template<typename T>
struct identity { typedef T type; };

template<typename T>
class CConstraint
{
public:

  template <typename TL>
  void Verify(int position, int constraints[])
  {
    Verify(position, constraints, identity<TL>());
  }

private:
  template<typename TL>
  void Verify(int, int[], identity<TL>)
  {

  }

  void Verify(int, int[], identity<int>)
  {

  }
};

14voto

Bobby Paulose Points 59

Il suffit de prendre le modèle de la spécialisation à l'extérieur de la déclaration de classe. gcc n'autorise pas inline modèle de spécialisation.

Comme autre option, tout simplement en supprimant ligne template<> semble fonctionner pour moi.

4voto

rursw1 Points 1860

gcc est correct. Membre spécialisations de modèle doivent être réalisés dans le espace de noms de la classe appartient. Essayez de le modifier:

template <> void  CConstraint::Verify<int>(int, int[])

1voto

M. Tibbits Points 3867

Vous pourrez peut-être pas explicitement spécialiser le membre modèle, mais vous pouvez partiellement spécialisés. Si vous ajoutez un second paramètre "int dummyParam" et également l'ajouter à la spécialisation, il devrait travailler avec les deux compilateurs.

Non pas que je le savais plus que 10 secondes à peine, mais une recherche sur google sur la même erreur, je suis tombé sur ce lien et cela a fonctionné pour mon modèle de spécialisation.

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