Sollte der Operator <=> Array-Vergleiche synthetisieren?

Sep 30 2020

Ich habe mit meiner eigenen Implementierung von std :: array gespielt und festgestellt, dass die Version von libc ++ explizit definierte Operatoren für jeden der Vergleiche verwendet (== ,! =, <,>, <=,> =). Ich dachte, ich könnte meinen Code vereinfachen, indem ich den Raumschiffoperator (<=>) von C ++ 20 implementiere. Als ich jedoch die Nicht-Mitglied-Vergleichsoperatoren durch auto operator<=>(const Array<TYPE,SIZE>&) const = default;im Strukturkörper ersetzte , gab GCC-Trunk an, dass die Funktion "implizit gelöscht wurde, weil die Standarddefinition fehlerhaft wäre". Einige Untersuchungen ergaben, dass das rohe Array-Mitglied der Schuldige war.

Auf dieser Webseite heißt es: "Der Compiler weiß, wie Mitglieder von Klassen, die Arrays sind, in ihre Listen von Unterobjekten erweitert und rekursiv verglichen werden." Und diese SO-Antwort zeigt an, dass nur kopierbare Arrays an der Vergleichssynthese teilnehmen.

Aus Neugier habe ich den Code über den ersten Link im Compiler Explorer ausgeführt. Es kann auch nicht auf gcc trunk kompiliert werden . Allerdings stellt Klirren Stamm erfolgreich den Code.

Meine Frage ist also: Welcher Compiler ist richtig? Sollte der Vergleich für Member-Arrays synthetisiert werden oder nicht?

Antworten

2 eerorika Sep 30 2020 at 21:44

Sollte der Operator <=> Array-Vergleiche synthetisieren?

Ja. Dies ist, was der Standard (endgültiger Arbeitsentwurf) sagt:

[class.compare.default]

Eine standardmäßige Vergleichsoperatorfunktion (12.6.2) für einige Klasse C ist eine ...

Die direkten Basisklassen-Unterobjekte von C ..., gefolgt von den nicht statischen Datenelementen von C, bilden in der Reihenfolge ihrer Deklaration in der Elementspezifikation eine Liste von Unterobjekten. In dieser Liste wird jedes Unterobjekt vom Array-Typ rekursiv auf die Reihenfolge seiner Elemente in der Reihenfolge des zunehmenden Index erweitert. Sei xi ein l-Wert, der das i-te Element in der erweiterten Liste von Unterobjekten für ein Objekt x (mit der Länge n) bezeichnet, wobei xi durch eine Folge von Konvertierungen von abgeleiteten zu Basis (12.4.3.1), Zugriffsausdrücke für Klassenmitglieder (12.4.3.1) gebildet wird 7.6.1.4) und Array-Indexausdrücke (7.6.1.1), die auf x angewendet werden.