11
votes

C ++ Modèle Spécialisation partielle - Spécialisez une fonction membre uniquement

heurté dans un autre problème de modèles:

Le problème: Je souhaite particulièrement spécialiser une classe de conteneurs (FOO) pour le cas que les objets sont des pointeurs et que je souhaite spécialiser uniquement la méthode de suppression. Devrait ressembler à ceci: p>

le code lib libéré strud> p> xxx pré>

le code de l'utilisateur strong> p >

foo<int>    fi;
foo<int*>   fpi;

int         i = 13;

fi.addSome (12);            
fpi.addSome (&i);

fpi.deleteSome (12);        // compiler-error: doesnt work
fi.deleteSome (&i);         // compiler-error: doesnt work
fi.deleteSome (12);         // foobase::deleteSome called
fpi.deleteSome (&i);        // foo<T*>::deleteSome called


5 Réponses :


11
votes

Seconde Solution (Correct One)
template <typename T>
class foo
{
public:
    void addSome    (T o) { printf ("adding that object..."); }
    void deleteSome (T o) { printf ("deleting that object..."); }
    void deleteSome (T* o) { printf ("deleting that object..."); }
};


5 commentaires

C'est une bonne suggestion, mais cela permet également aux cas suivants de compiler sans erreur: - FOO fi; int i; FI.Deletesome (& I); Où il devrait oser uniquement être capable de "supprime" de type int


@Kirill. Ça ne marchera pas. Supposons que nous utilisions foo . Ensuite, FOO a 3 fonction: addexe (myClass * o) , Suppression (myClass * o) et Suppression (myClass ** o) . La dernière fonction ne sera jamais appelée.


Je vais faire des courses maintenant. Mais je vous laisserai une note: vous ne pouvez pas mettre la spécialisation explicite pour le modèle de membre dans le corps de la classe. Vous ne pouvez pas non plus le mettre à l'extérieur, car cela ne fonctionnera pas: Modèle Modèle <> vide FOO :: deletésomeHelper (T & O) {} (comme s'il y a peut-être ne pas être des clauses de paramètres de modèle avant un modèle <> ).


@LitB, maintenant je vois de quoi vous parlez. Fixé.


+1 pour la deuxième solution. Cela semble bon. Voir ci-dessous pour une idée utilisant Boost :: Supprimer_Pointer, en évitant la fonction supplémentaire.



1
votes

Vous pouvez utiliser l'héritage pour que cela fonctionne:

template <typename T>
class foobase
{
public:
    void addSome    (T o) { printf ("adding that object..."); }
    void deleteSome (T o) { printf ("deleting that object..."); }
};

template <typename T>
class foo : public foobase<T>
{ };

template <typename T>
class foo <T *> : public foobase<T>
{
public:
    void deleteSome (T* o) { printf ("deleting that PTR to an object..."); }
};


6 commentaires

Merci Tony, je suppose que je vais avec votre solution.


Cette solution n'est pas évolutive. Supposons que vous souhaitiez ajouter une nouvelle fonction dosage (t O) et la spécialiser pour que les objets soient STD :: Liste .


Aussi cette solution est fausse. Supposons que nous utilisons FOO . Aucune fonction de la classe de la classe foobase peut appeler Supprimer car Supprimer (t) sera appelé plutôt que Suppression (t *) .


Euh, ne devrait-il pas être Classe FOO : Public FOOBASE (Notez le deuxième * )?


La réponse de Kirill manque l'une des utilisations de spécialisation, à savoir spécialiser une classe existante pour votre propre nouveau type (sans avoir la possibilité de modifier la classe existante). La solution de Tony est la plus générale.


-1 Il n'y a aucune raison Supprimer doit être dans la classe de base sans être virtuelle, ramasser l'une des options.



2
votes

Créer une classe de base pour une fonction unique Supprimer xxx

faire une spécialisation partielle xxx

Utilisez votre classe de base xxx


0 commentaires

10
votes

Une autre solution. Utilisez la fonction auxiliaire deletésomeHelp code>.

template <typename T>
class foo {
 public:    
   void addSome    (T o) { printf ("adding that object..."); 
   template<class R>
   void deleteSomeHelp (R   o) { printf ("deleting that object..."); }};
   template<class R>
   void deleteSomeHelp (R * o) { printf ("deleting that PTR to an object..."); }};
   void deleteSome (T o) { deleteSomeHelp(o); }
}    


2 commentaires

Crazy Stuff :), mais je suis confronté au même problème ici, de sorte qu'un foo puisse appeler une suppression avec un pointeur donné.


+1 ressemble à celui que j'utiliserais tout de suite. C'est beaucoup plus simple et fait le travail.



3
votes

Je n'ai pas encore vu cette solution, en utilisant Boost's activer_if , isameame et retirer_pointer pour obtenir deux fonctions dans une classe, sans héritage ou autre cruft.

voir ci-dessous pour une version en utilisant seulement retirer_pointer . xxx

une version simplifiée est: xxx

et cela fonctionne sur MSVC 9: (a commenté les lignes qui donnent des erreurs, car elles sont incorrectes, mais bien d'avoir pour tester) xxx


0 commentaires