28 votes

operator ++ en tant que suffixe et préfixe ne fonctionne pas avec clang

J'ai essayé d'écrire un opérateur qui peut être utilisé à la fois comme un préfixe et d'un suffixe de l'opérateur

#include <iostream>
#include <utility>

struct B { 
  // ...
};

template<typename ...T>
void operator++(B, T...) {
  std::cout << ((sizeof...(T) == 0) ? "prefix" : "postfix") << std::endl;
}

int main() {
  B b;
  b++;
  ++b;
}

GCC compile et fonctionne très bien avec cela, mais clang dit

principal.rpc:9:24: erreur: paramètre de surcharge de la post-incrémentation de l'opérateur doit être de type " int " (et non pas 'T...')

void operator++(B, T...) {

Qui a raison?


Merci à toute personne qui m'a aidé à comprendre le comportement de GCC. J'ai déposé une nouvelle Clang rapport de bug:

http://llvm.org/bugs/show_bug.cgi?id=14995

7voto

Andy Prowl Points 62121

RÉPONSE ORIGINALE à cette question: (pas supprimé, car il peut contenir des informations utiles)

Je dirais que tout se résume à la question de savoir si un opérateur surchargé modèle est considéré comme un opérateur surchargé ou pas. Logiquement, j'aime à penser que ce n'est pas le cas, et Clang est faux: je crois que le modèle devrait d'abord être choisi comme candidat à la surcharge de résolution basée sur le nom et la signature de compatibilité, alors instancié, puis (éventuellement) sélectionné. La façon dont je le vois, seulement après l'instanciation le compilateur doit vérifier si les résultats de la fonction a le bon nombre d'arguments ou pas.

Mais ce n'est que mon avis. Par § 13.5.7/1 à propos de la surcharge de la postfix operator ++:

"Si la fonction est une fonction de membre avec un paramètre (qui doit être de type int) ou un non-membre de la fonction avec deux paramètres (le deuxième de ce qui doit être de type int), il définit la postfix opérateur d'incrémentation ++ pour les objets de ce type"

La Norme ne semble pas préciser si une fonction de modèle doit être considérée comme une fonction pour ce qui concerne les restrictions sur la signature de juridique la surcharge de l'opérateur (au moins, je ne pouvais pas trouver n'importe quelle phrase qui permet de résoudre cette ambiguïté). Aussi longtemps que cela est vrai, cette question ne peut guère être donné une réponse claire, et nous nous retrouvons avec des opinions.

Mais je voudrais mentionner un autre aspect de la question: la cohérence.

Même s'il est vrai que le code de la question du texte ne compile pas sur Clang, le suivant n':

template<typename... Ts>
int operator + (X x1, Ts... args)
{
    return 0;
}

Je ne vois pas de différence conceptuelle entre les deux cas: si la signature de l'opérateur de surcharge doit être vérifié avant l'instanciation, puis la définition ci-dessus ne devrait pas compiler soit. Si ce n'est pas le cas, alors le code dans la question du texte devrait compiler.

Donc, la réponse, à mon avis, c'est que GCC est de droite, ou les deux sont mauvais.

Mise à JOUR:

Comme @JesseGood et @SethCarnegie correctement souligner, par 14.7/4:

"Une spécialisation est une classe, une fonction ou un membre de la classe qui est instancié ou explicitement spécialisés."

En outre, par 14.6/8:

"Pas de diagnostic doit être délivré pour un modèle pour lesquelles une spécialisation peuvent être générés."

Ainsi, il semble Clang est en effet mal et aucune erreur de compilation doit être produite pour la fonction opérateur de modèle dans la question du texte.

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