6
votes

Modèle spécialisation partielle

Est-ce que quelqu'un sait selon quel code de règles ci-dessous ne compile pas? XXX

Veuillez consulter le commentaire à l'intérieur du code.


0 commentaires

3 Réponses :


5
votes

Vous devez utiliser typename comme, xxx

c'est parce que B :: Type est un nom dépendant. Donc typename est requis!

-

edit:

même après avoir mis typename , il ne compile pas. Je pense que c'est parce que la déduction du type t dans b de x est difficile, ou éventuellement impossible, pour le compilateur. Je crois donc son contexte non déduit.

Voir un exemple similaire ici et la discussion:

paramètres de modèle dans des contextes non déduits dans des spécialisations partielles


Cependant, si vous changez la spécialisation à cette : xxx

alors il devient le contexte en déductible, et aussi compilerait.


8 commentaires

@Navaz j'ai fait comme vous l'avez proposé et j'ai: Erreur 1 erreur C2764: 'T': paramètre de modèle non utilisé ou déductible dans une spécialisation partielle 'X :: Type *>' de vs 2010


@Il n'y a rien. Parce que ça ne peut pas. Ce que vous essayez de faire est au-delà de la portée du compilateur.


@Cashcow Que voulez-vous dire par au-delà de la portée du compilateur (et s'il vous plaît, je n'essaie pas de vous rendre avec vous ou avec quelqu'un ici, j'essaie simplement de comprendre)


@Ille n'est rien que nous puissions faire: S'il vous plaît voir mon édition. Et le lien vers un bon sujet discute du même problème!


@Nawaz en effet votre deuxième serait déductible, B ne peut jamais signifier une chose ici.


Cela devrait compiler, je pense. Cela ne devrait jamais correspondre à cette spécialisation.


@Johannes: la spécialisation ne compile pas. Voir vous-même: Ideone.com/iwnue


J'ai dit "ça devrait compiler". Je n'ai pas dit "Ideone l'accepte". C'est probablement un avertissement qui a été émis comme une erreur à cause de -werror et, sinon, il est peut-être un bug de GCC. Je parle de la mémoire, donc je me tromperais. Voir la principale émission 549 pour le rapport de publication de ce std.org/jtc1/sc22/wg21/docs/cwg_active.html#549 . Vous pouvez appliquer la règle 14.6p8 («Si aucune spécialisation valide ne peut être générée ...»), mais c'est une règle très faible à utiliser pour émettre un diagnostic ici, à mon avis et je pense qu'il n'a pas de contextes non déduits des spécialisations partielles à l'esprit.



10
votes

Comment pensez-vous que cela fonctionnera? Le compilateur cherchera à voir s'il y a une classe T quelque part qui a un "type" Typef à votre classe?

Ce n'est tout simplement pas. Même si c'est un pointeur. P>

N'oubliez-vous probablement que votre modèle B est vraisemblablement spécialisé dans des endroits de sorte que le type ne soit pas toujours T *, mais il ne peut pas le déduire avec ingénierie inverse. P>

Pour ceux qui ne comprenaient pas complètement ma réponse, ce que vous demandez au compilateur de faire est de trouver une classe u telle que B :: Type est la classe que vous transmettez sous forme de paramètre. P>

class Foo;
class Bar;

template<> struct B<Foo>
{
  typedef int type;
};

template<> struct B<Bar>
{
  typedef int type;
};

X<int*> // ambiguous, T is Foo or Bar?


8 commentaires

Je ne comprends pas vraiment cette réponse. Le compilateur sait Quelle classe à utiliser - B . Chaque fois que x est instancié, le compilateur est absolument capable de rechercher toutes les spécialisations partielles de x pour les plus spécifiques. En fait, c'est ce que toujours fait. Par conséquent, la réponse de Nawaz est correcte.


(Suite) ou plutôt, je Attendez-vous à la réponse Nawaz 'pour être correcte. Clairement, cela ne fonctionne pas, mais je ne comprends pas la plainte du compilateur (le message de GCC est similaire à celui de VS 2010).


La réponse de Kondrad Nawaz ne peut pas être correcte s'il ne compile pas, c'est ce que je pense quand même.


@Kondrad à votre dernier commentaire: C'est exactement ce que je suis coincé avec. Selon quelle «balle» dans STD, cela ne compile pas?


@Konrad et @Ille n'est rien: je me demande aussi ce que mon code ne compile pas, bien que cela me semble correct. Ideone.com/iwnue


Le compilateur ne sait pas quelle classe à utiliser. Il cherche une classe u telle que b :: Type est T. Cela peut arriver que u = t, mais il n'y a pas de telle garantie.


@CashCow "Il cherche une classe u telle que b :: type est T" - pourquoi devrait-il? t est lié et bien connu dans le contexte afin qu'il devrait rechercher B :: Type , pas pour B :: Type < / code> pour certains u . Le compilateur doit pouvoir effectuer une substitution directe ici.


@Konrad Regardez la définition du modèle, ce n'est pas x il est x :: Type> Le T dans la template définition ci-dessus est trompeur. Dans mon exemple, vous écririez x pas x ou x



0
votes

En supposant que vous avez déjà ajouté typename comme suggéré par Nawaz.

Le problème est expliqué exactement dans le message d'erreur que vous rencontrez: "Le paramètre Modèle n'est pas déductible dans la spécialisation partielle B :: Type * . Le problème est que B :: Type et t est exactement le même pour tous les types t . Considérez l'exemple suivant: xxx

le résultat de la ligne (*) est un type myClass2 qui est essentiellement myClass1 . donc, obj1 et obj2 doit être des objets de la même classe. Maintenant, quelle version de modèle x devrait-il utiliser?

Si vous attendez la version spécialisée de X , dites-moi si la réponse doit être la même si la ligne (*) est supprimée (et évidemment obj2 aussi). Toujours obj1 devrait être la version spécialisée de x comme ligne (*) n'a rien à voir avec il.

Mais maintenant nous nous attendons à ce que le compilateur soit Détecter que certains types peuvent être potentiellement déclarés comme B :: Type Bien que nous ne le faisons jamais. Nous nous attendons à ce que le compilateur vérifie toutes les instanciations de modèles possibles pour vérifier s'il n'y a pas d'étrange Typedef dans l'un d'entre eux.

J'espère que cela clarifie pourquoi une telle spécialisation ne peut être traitée par le compilateur.


une alternative qui pourrait aider

Je pense que votre problème pourrait être attaqué en créant une classe de trait pour marquer explicitement des types qui devraient être traités de manière particulière. Quelque chose comme ceci: xxx

En outre, vous pourriez être intéressant comment il se fait dans la bibliothèque Boost, en particulier BOOST.TYPE_TRAITITS


5 commentaires

"Le problème est que b :: type et t est identique pour tous les types t " - Non. I> Pas Un problème (ou ne devrait pas être). "Maintenant, quelle version du modèle X devrait-elle utiliser?" - Évidemment, la version spécialisée parce que vos types sont les deux pointeurs. L'utilisation de B :: Type au lieu de t ici est complètement non pertinent. Ce qui est pertinent, c'est que la spécialisation est un pointeur .


Si vous souhaitez avoir une version spécialisée pour tous les pointes, vous devez avoir x et non x :: type *> . Ce dernier suggère de vouloir la spécialisation que pour certains pointeurs , mais pas tous. que , et non le fait que vous avez un pointeur, c'est un problème. Vous obtiendrez exactement la même erreur si vous supprimez * .


"L'utilisation de B :: Type au lieu de juste t ici est complètement non pertinente" -> elle est pertinente et cruciale pour le compilateur. Il ne peut pas déduire ce que B est nécessaire pour obtenir une correspondance avec le type de courant que vous souhaitez instancier. Morover, il ne sait même pas qu'il devrait réellement examiner la classe de classe B lors de la recherche d'un match.


Pourquoi est-ce un problème cependant? Pourquoi ne peut-il pas déduire b ? (En fait, il n'y a pas de déduction, c'est un remplacement simple).


Imaginez que vous avez 1000 classes de modèle qui ont des typées à l'intérieur. Pensez-vous que le compilateur vérifiera tous pour un match? Et quoi s'il y a plus d'un match?