Comprendre (simple?) C ++ Spécialisation de modèle partiel
Remarque: ce qui semble être un repost d'un problème: C++ - Surcharge basé sur un modèle de la méthode de classe, une partie specilization de cette méthode
J'ai cuit un problème que j'ai avec C++ template de la spécialisation vers le bas pour un cas simple.
Il se compose d'un simple 2-paramètre de la classe de modèle Thing
où je tiens à se spécialiser Thing<A,B>::doSomething()
pour B=int
.
#include <cstdio>
//
//A 3-parameter template class.
//
template <class A, class B>
class Thing
{
public:
Thing(A a, B b) : a_(a), b_(b) {}
B doSomething();
private:
A a_;
B b_;
};
//
//The generic case works as expected.
//
template <class A, class B>
B Thing<A,B>::doSomething()
{
return b_;
}
//
//This specialization does not work!
//
template <class A>
int Thing<A,int>::doSomething()
{
return b_+1;
}
int main( int argc, char** argv )
{
//Setup our thing.
Thing<double,int> thing(1.0,2);
//This doesn't compile - but works with the generic case.
printf("Expecting 3, and getting %i\n", thing.doSomething());
//Clean up.
return 0;
}
Malheureusement, g++
se termine avec l'erreur:
partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’
La clang++
compilateur est un peu plus verbeux, mais a le même problème:
partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifier 'b_'
return b_+1;
^
2 errors generated.
J'ai lu et entendu que partielle spécialisations de modèle sur les fonctions ne sont pas admis - mais j'ai pensé que j'étais partiellement spécialisé sur les classes de Thing
dans ce cas.
Des idées?
Ce que j'ai fait: Une solution de contournement, comme déterminé dans le lien fourni par le a accepté de répondre:
template< class T >
inline T foo( T const & v ) { return v; }
template<>
inline int foo( int const & v ) { return v+1; }
//
//The generic case works as expected.
//
template <class A, class B>
B Thing<A,B>::doSomething()
{
return foo(b_);
}
source d'informationauteur Dan | 2011-05-26
Vous devez vous connecter pour publier un commentaire.
Partielle de la spécialisation d'un modèle de fonction, si elle est membre de la fonction de modèle autonome ou de la fonction de modèle, n'est pas autorisé par la Norme:
Mais vous pouvez partiellement spécialiser le modèle de classe elle-même. Vous pouvez faire quelque chose comme ceci:
Noter que lorsque vous avez en partie spécialiser une classe de modèle, puis le paramètre de modèle-liste des membres et leur fonction (dans sa définition en dehors de la classe), doit correspondre à le paramètre de modèle de liste de la classe de modèle partiel de la spécialisation. Cela signifie que, pour la ci-dessus partielle de la spécialisation de la classe de modèle, vous ne pouvez pas définir ce:
Il n'est pas permis, car le paramètre de modèle de liste de définition de la fonction ne correspond pas au paramètre de modèle de liste de la classe de modèle partiel de la spécialisation. §14.5.4.3/1 de la Norme (2003) dit,
Pour en savoir plus, lire ma réponse ici:
C++ - Surcharge basé sur un modèle de la méthode de classe, une partie specilization de cette méthode
Quelle est donc la solution? Souhaitez-vous en partie spécialiser votre classe ainsi que tout le travail répétitif?
Une solution simple serait de travail de la délégation, à la place de la en partie spécialisée de la classe de modèle. Écrire un autonome modèle de fonction et de se spécialiser comme suit:
Et ensuite appeler cette fonction à partir d'un modèle
doSomething()
fonction de membre:Puisque dans votre cas particulier,
doTheActualSomething
besoin de connaître la valeur de un seul membre, à savoirb_
la solution ci-dessus est très bien, que vous pouvez transmettre la valeur de la fonction en tant qu'argument dont le type est le modèle type argumentB
et de la spécialisation pourint
est possible d'être plein de spécialisation.Mais imaginez si elle a besoin d'accéder à plusieurs membres, type de chacun dépend du modèle de type liste d'arguments, puis de définir un stand-alone, fonction modèle ne résout pas le problème, car il n'y en aura plus d'une type argument de la fonction de modèle, et vous ne pouvez pas partiellement spécialiser la fonction pour juste, disons, un type (comme il n'est pas permis).
Dans ce cas, vous pouvez définir un modèle de classe au lieu de cela, ce qui définit une statique non-modèle de fonction de membre
doTheActualSomething
. Voici comment:Notez que vous pouvez utiliser
thing
pointeur pour accéder à tout membre de la classe. Bien sûr, si elle doit accéder aux membres privés, alors vous avez à fairestruct Worker
un ami deThing
modèle de classe, comme:Maintenant déléguer le travail à l'ami:
Deux points à noter ici:
doTheActualSomething
n'est pas une fonction membre modèle. Ses pas la classe englobante qui est modèle. Par conséquent, nous pouvons partiellement spécialiser le modèle de classe à tout moment, pour obtenir l'effet désiré de la partielle fonction membre template de la spécialisation.this
pointeur en argument à la fonction, nous pouvons accéder à tout membre de la classeThing<A,B>
même privé des membres, commeWorker<T,U>
est aussi un ami.Complète de démonstration en ligne : http://www.ideone.com/uEQ4S
Maintenant il y a encore une chance d'amélioration. Maintenant, toutes les instanciations de
Worker
modèle de classe sont des amis de tous les instanciation deThing
modèle de classe. Donc on peut limiter ce nombre à beaucoup d'amitié:Maintenant, une seule instanciation de
Worker
modèle de classe est un ami de l'un à l'instanciation deThing
modèle de classe. C'est un-à-un à l'amitié. C'est,Worker<A,B>
est un ami deThing<A,B>
.Worker<A,B>
n'est PAS un ami deThing<A,C>
.Ce changement nous oblige à écrire le code d'une façon un peu différente. Voir la démo complète, avec la commande de classe et des définitions de fonction et tous:
http://www.ideone.com/6a1Ih
C'est très souvent trouvé le problème, et il est étonnamment simple solution. Je vais le montrer dans un exemple artificiel, parce que c'est plus claire que l'utilisation de votre code, et vous aurez à le comprendre pour l'adapter à votre code
Explicitement spécialisée fonctions n'est jamais (ou presque jamais?) le droit chemin. Dans mon travail en tant que programmeur, je n'ai jamais explicitement spécialisées un modèle de fonction. La surcharge et partielle de la commande est supérieur.