5 votes

Spécialisation d'un modèle de fonction dans une autre classe/espace de nommage ?

NOTE : Cette question n'est que vaguement liée à tinyxml, mais le fait d'inclure des détails comme ceux-là peut aider à mieux illustrer le concept.

J'ai écrit un modèle de fonction qui va itérer à travers les enfants d'un nœud XML parent, récupérer la valeur de l'élément enfant et ensuite pousser la valeur de cet élément enfant dans un vecteur.

La partie "récupérer la valeur" est également écrite comme un modèle de fonction :

c'est-à-dire

template <typename Type>
Type getXmlCollectionItem(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

Il existe des spécialisations pour la partie récupération, pour retourner différents types de valeurs d'éléments enfants, par exemple std::string et d'autres objets personnalisés.

c'est-à-dire

template <>
std::string getXmlCollectionItem<std::string>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

template <>
MyObject getXmlCollectionItem<MyObject>(
    const char* elementName, TiXmlNode* child, TiXmlNode* parent);

Tout cela fonctionne parfaitement bien, mais je me suis rendu compte qu'il serait très utile de disposer d'une bibliothèque de fonctions partagées pour traiter les fichiers tinyxml.

Question : Est-il possible de déclarer un modèle de fonction dans un seul espace de nom, par ex. namespace UtilityFunctions qui n'a aucune connaissance des types d'objets spécifiques tels que 'MyObject' et ensuite déclarer et définir des spécialisations de ce modèle de fonction dans d'autres espaces de noms qui ont la connaissance de types d'objets spécifiques tels que 'MyObject' ?

Mon intuition est que ce n'est pas possible, mais le concept d'avoir un modèle de fonction commun me semble suffisamment utile pour qu'il y ait un moyen alternatif de se rapprocher de la fonctionnalité que je recherche...

Toutes nos excuses si la terminologie est incorrecte ou si l'explication n'est pas claire. J'ai fait beaucoup de recherches sur ce sujet (pour arriver à la spécialisation des modèles de fonctions dans le même espace de noms) mais je n'ai pas encore trouvé de réponse définitive.

5voto

bronekk Points 1409

Il n'est pas possible d'écrire dans un espace de nom une spécialisation d'un modèle défini dans un autre espace de nom (puisque ce ne serait pas une spécialisation de ce modèle, étant défini dans un autre espace de noms, ce serait un modèle différent).

Cependant, il est tout à fait possible d'étendre l'espace de noms où le modèle a été défini à l'origine, en écrivant votre spécialisation dans un fichier source totalement séparé.

Voici donc ce que vous no puede faire :

namespace A { namespace B {
  template <typename T> int foo(T) {throw 1;}
}}

template <> int A::B::foo(int) {throw 0;}

Vous pouvez voir un beau message d'erreur pour ce qui précède à l'adresse suivante http://www.comeaucomputing.com/tryitout/

"ComeauTest.c", line 5: error: the initial explicit specialization of function
          "A::B::foo(T) [with T=int]" must be declared in the namespace
          containing the template
  template <> int A::B::foo(int) {throw 0;} 
                        ^

Voici ce que vous peut faire :

namespace A { namespace B {
  template <typename T> int foo(T) {throw 1;}
}}

namespace A { namespace B {
  template <> int foo(int) {throw 0;}
}}

Y a-t-il une raison pour laquelle ce serait un problème ?

De plus, si vous déléguez le travail à une fonction associée à l'objet que vous lisez (qu'il s'agisse d'un membre ou d'une fonction libre), vous pouvez compter sur le fait que cette fonction sera trouvée par ADL et appelée. Cela signifie que vous devriez être en mesure de minimiser le nombre de spécialisations comme celles mentionnées ci-dessus.

Voici un exemple :

namespace A { namespace B {
  template <typename T> int bar(T t) {return 0;}
  template <typename T> int foo(T t) {return bar(t);}
}}

namespace C {
  struct Bah {};
  int bar(Bah&) {return 1;}
}

int main(int argc,char** argv) 
{
  C::Bah bah;

  std::cout << A::B::foo(0) << std::endl;
  std::cout << A::B::foo(bah) << std::endl;
}

Publié sur pour ajouter un exemple

1voto

Sadanand Points 191

Le point ici est " Chaque déclaration pour un modèle doit être placée dans le même espace de noms, tout comme les déclarations répétées de toute autre entité nommée ".

La déclaration/définition dans un espace de noms différent n'est pas valide, Pour plus d'informations, veuillez consulter le 12e point de l'annexe 1. FAQ

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