10
votes

Pourquoi le compilateur ne donne-t-il pas une erreur en définissant des spécialisations similaires?

Quelle est la procédure de comparaison des spécialisations Modèle ? La norme n'est pas détaillée sur ce point (ou je manque le bon endroit).
Ma question n'a rien à voir avec décider de la spécialisation à utiliser lors de l'instanciation. S'il vous plaît, ne commencez pas à ce sujet. La question concerne la comparaison des spécialisations les unes aux autres pour décider si une spécialisation particulière est déjà définie ou non encore.

considère ce code d'exemple: xxx

Quand j'essaie de compiler Ce code avec MSVC, je reçois une erreur pour la tentative d'instanciation à l'intérieur de la fonction principale :

CPPTEST1.CXX (15): Erreur C2752: ' coretemplate ': Plus d'une spécialisation partielle correspond à la liste des arguments de modèle

Pour moi, il serait plus logique de délivrer une erreur pour tenter de déclarer des spécialisations de modèles identiques. Je ne vois aucune différence entre les spécialisations ci-dessus.

Donc, quelqu'un connaît-il des règles de comparaison de spécialisations de modèles? Articles, liens, livres, etc. aidera également.


2 commentaires

Bonne question. Édité avec une position appropriée et des balises.


FYI: Clang 3.1 semble avoir un comportement similaire.


3 Réponses :


0
votes

Pour moi, il serait plus logique de délivrer une erreur pour tenter de Déclarez des spécialisations de modèles identiques. P>

qui ne se produirait pas, car coretemplate code> et coretemplate code> générera différents types. Strike> P>

ci-dessous est ma supposition:
Le compilateur peut ne pas effectuer le supplément sainte / sens commun em> checks pour modèle code> corps.
Une fois que vous avez instancié un modèle code> code>, à ce moment-là compilateur recherche le type de correspondance et ramasse le meilleur. S'il ne correspond pas à un seul fort>, il donne une erreur de compilateur soit pour no-match em> ou match multiple em>. P> Par exemple: P>

template<typename T>
void foo ()
{
  T::x();
}

int main ()
{
}


5 commentaires

Pas vraiment. Si je mettais une seconde spécialisation dans le code deux fois, j'obtiens immédiatement: CPPTest1.cxx (14): Erreur C2953: 'Coretemplate ': Modèle de classe a déjà été défini . En outre, la langue permet de mettre en œuvre des méthodes de spécialisation en dehors de la définition. Depuis le compilateur de l'en-tête de la méthode doit comprendre quelle spécialisation appartient cette méthode.


La torsion est la triche, la nature même de C (et C ++) est de rechercher seulement des déclarations précédemment déclarées, de sorte que bien sûr Ça fonctionne, mais il est néanmoins surprenant.


@Matthieum., La terminologie derrière la "Twist" est que, vous pouvez très bien inclure les deux spécialisations séparément dans 2 fichiers d'en-tête différents et les utiliser dans différents fichiers .cpp. Tout va toujours compilera bien. Le problème ne viendra que lorsque les deux sont visibles pour toute instanciation.


@Kirillkobelev, répétant que le même corps de classe sera définitivement une erreur. Cela équivaut à inclure un seul fichier d'en-tête plusieurs fois sans que les gardes incluent. :) Ici, les deux spécialisations sont différentes et elles peuvent coexister, comme je l'ai montré par exemple.


@iammilind: Je ne pense pas que vous vouliez dire la terminologie (qui parle d'expliquer la sémantique). Quoi qu'il en soit, je suis d'accord avec vous que cela puisse se produire à l'état sauvage et conduira probablement à une violation de l'ODR.



5
votes

La norme est spécifique pour indiquer que cela ne se produit que lorsque vous essayez d'instancier le modèle (§14.5.4.1 / 1):

Lorsqu'un modèle de classe est utilisé dans un contexte nécessitant une instanciation de la classe , il est nécessaire de déterminer si l'instanciation doit être générée à l'aide du modèle principal ou de l'une des spécialisations partielles. [emphase ajoutée]

Malheureusement, le reste de votre question ne peut être répondu sans discuter de la manière de décider quelle spécialisation à utiliser lors de l'instanciation. Voici le texte de la norme (continuant de l'extrait ci-dessus):

Ceci est fait en faisant correspondre les arguments de modèle du modèle de classe Spécialisation avec les listes d'arguments de modèle des spécialisations partielles.

  • Si exactement une spécialisation correspondante est trouvée, l'instanciation est générée à partir de cette spécialisation.
  • Si plus d'une spécialisation correspondante est trouvée, les règles de commande partielle (14.5.4.2) sont utilisées pour déterminer si l'une des spécialisations est plus spécialisée que les autres. Si aucune des spécialisations n'est plus spécialisée que toutes les autres spécialisations correspondantes, l'utilisation du modèle de classe est ambiguë et le programme est mal formé.

    Donc, il ne tente jamais de comparer les modèles directement les uns aux autres. Il tente plutôt de trouver une spécialisation qui correspondra aux arguments fournis. Si plusieurs correspondances, il tente de choisir le plus spécialisé en fonction des règles de commande partielle. Si non plus est plus spécialisé que l'autre, l'instanciation est ambiguë et la compilation échoue.

    Maintenant, il est certainement vrai qu'aucune de ces spécialisations ne pourrait jamais être utilisée, car il y aurait toujours une ambiguïté - si l'autre correspondait, l'autre correspondait évidemment aussi bien. Il n'y a tout simplement aucune obligation pour le compilateur de détecter ou de diagnostiquer cela. Dans ce cas exactement (des spécialisations essentiellement identiques) qui seraient probablement faciles, mais il y a presque certain autre cas où il serait beaucoup plus difficile, donc (apparemment) le Comité a décidé que le compilateur n'avait même pas à essayer.


3 commentaires

Je pense que tout cela revient à la règle d'une définition. Il ne peut y avoir qu'une définition d'un modèle et une spécialisation partielle est un modèle. Nous sommes donc vraiment laissés dans la question de savoir si deux spécialisations sont considérées comme le même modèle et que je ne trouve rien dans la norme qui définit clairement cela. En étudiant le comportement de g ++, il considère que deux spécialisations sont le même modèle si les listes d'arguments de modèle sont identiques, tout en ignorant les noms spécifiques.


Merci pour le commentaire raisonnable.


Ce n'est pas complètement vrai. Le compilateur doit comparer les listes d'arguments de spécialisation partielle. Pensez à des définitions hors ligne des fonctions des membres des spécialisations partielles. Le compilateur doit associer la définition à l'une d'elles.



1
votes

ah, mais ils sont pas em> les mêmes car ils n'utilisent pas les mêmes paramètres. Utilisation de Clang et de votre exemple original:

template <class x1, class x2>
struct Core { };

template <class x1>
struct Core<x1*, x1*> { int spec; Core() { spec = 1; } };
// note: previous definition is here

template <class x1>
struct Core<x1*, x1*> { int spec; Core() { spec = 2; } };
// error: redefinition of 'Core<type-parameter-0-0 *, type-parameter-0-0 *>'


0 commentaires