tutorial - operator c++ declaration



operator++ als Postfix und Präfix funktioniert nicht mit clang (1)

Ich habe versucht, einen Operator zu schreiben, der sowohl als Präfix als auch als Postfixoperator verwendet werden kann

#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 kompiliert und funktioniert gut damit, aber Clang sagt

main.cpp: 9: 24: error: Parameter des überladenen Post-Inkrement-Operators muss den Typ 'int' haben (nicht 'T ...')

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

Wer hat Recht?

Vielen Dank an alle, die mir geholfen haben, das Verhalten von GCC zu verstehen. Ich habe einen neuen Clang-Fehlerbericht eingereicht:

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


ORIGINAL ANTWORT: ( nicht gelöscht, da es nützliche Informationen enthalten kann )

Ich würde sagen, es läuft alles darauf hinaus, ob eine überladene Operatorvorlage als überladener Operator angesehen wird oder nicht. Logischerweise möchte ich denken, dass dies nicht der Fall ist, und Clang ist falsch: Ich glaube, dass die Vorlage zuerst als Kandidat für die Überladungsauflösung basierend auf Namens- und Signaturkompatibilität ausgewählt, dann instanziiert und dann (möglicherweise) ausgewählt werden sollte. So wie ich es sehe, sollte der Compiler erst nach der Instanziierung prüfen, ob die resultierende Funktion die richtige Anzahl von Argumenten hat oder nicht.

Aber das ist nur meine Meinung . Nach § 13.5.7 / 1 zum Überladen des Postfix- operator ++ :

"Wenn die Funktion eine Elementfunktion mit einem Parameter (der vom Typ int sein soll) oder eine Nichtmitgliedsfunktion mit zwei Parametern (von denen der zweite vom Typ int sein soll) definiert, definiert sie den Postfix-Inkrementoperator ++ für Objekte von diesem Typ "

Der Standard scheint nicht zu klären, ob eine Funktionsvorlage als eine Funktion für die Beschränkungen der Signatur von Überbelastungen von Rechtsoperatoren betrachtet werden sollte (zumindest konnte ich keinen Satz finden, der diese Mehrdeutigkeit löst). Solange dies zutrifft, kann diese Frage kaum beantwortet werden, und uns bleiben Meinungen .

Aber ich möchte noch einen weiteren relevanten Aspekt der Frage erwähnen: Konsistenz .

Obwohl es richtig ist, dass der Code in dem Fragetext nicht auf Clang kompiliert wird, geschieht Folgendes:

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

Ich sehe keinen konzeptionellen Unterschied zwischen den beiden Fällen: Wenn die Signatur der Operatorüberladung vor der Instanziierung überprüft werden soll, dann sollte die obige Definition auch nicht kompiliert werden. Wenn dies nicht der Fall ist, sollte der Code im Fragetext kompiliert werden.

Die Antwort ist meiner Meinung nach, dass entweder der GCC recht hat oder beide falsch liegen.

AKTUALISIEREN:

Wie @JesseGood und @SethCarnegie richtig angeben, per 14.7 / 4:

"Eine Spezialisierung ist eine Klasse, Funktion oder ein Klassenmitglied, das entweder instanziiert oder explizit spezialisiert ist."

Außerdem, per 14.6 / 8:

"Es darf keine Diagnose für eine Vorlage ausgegeben werden, für die eine gültige Spezialisierung generiert werden kann."

Daher scheint es, dass Clang tatsächlich falsch ist und kein Kompilierungsfehler für die Operatorfunktionsvorlage im Fragetext erzeugt werden muss.





language-lawyer