__builtin_round ist kein konstanter Ausdruck

8

In G ++ sind verschiedene eingebaute mathematische Funktionen unter bestimmten Bedingungen consExpr. Zum Beispiel kompiliert das folgende:

%Vor%

Sie sind nicht immer gleich, aber es kommt auf das Argument an. Zum Beispiel führt __builtin_sqrt(NAN) zu einem Kompilierungsfehler, wenn es als Konstantenausdruck verwendet wird.

Aber ich treffe einen seltsamen Fall, wo es scheint, dass es constexpr sein sollte, aber es ist nicht:

%Vor%

Dies erzeugt:

%Vor%

Ich habe Variationen des obigen Codes ausprobiert, und ich habe Folgendes gefunden:

  • Das __builtin_round hat eine besondere Rolle in dem Problem. Ersetzen Sie ihn durch eine andere eingebaute mathematische Funktion wie sqrt oder pow , um den Fehler zu beheben. So scheint, dass __builtin_round einfach keine consExpr-Unterstützung hat. Aber ...
  • Wenn value() durch ein Literal 1.23 ersetzt wird, wird auch der Fehler entfernt.
  • Durch das Entfernen von __builtin_sqrt und das Zurücklassen von __builtin_round(value()) wird der Fehler ebenfalls entfernt.

Ich würde gerne wissen, warum sich round auf diese Weise verhält und ob es eine Problemumgehung gibt.

HINWEIS . Ich bin mir bewusst, dass die eingebauten mathematischen Funktionen mit ihrem Kontextergebnis eine nicht standardmäßige Compiler-spezifische Eigenschaft sind. Bitte lehre mich nicht darüber, wie ich das nicht benutzen sollte, oder wie ich nicht versuchen sollte, Zeit für Mathe zu kompilieren. In meinem Fall ist es ein wichtiges Merkmal, consExprmath zu haben, und mir geht es gut, abhängig von G ++.

    
Ambroz Bizjak 03.05.2014, 17:39
quelle

3 Antworten

3

Ich habe eine Idee von einer anderen Problemumgehung.

Es gibt: Verwenden Sie eine Hilfsfunktion pass_through

%Vor%

benutze es so:

%Vor%

Dieser Code wird ohne Fehler in G ++ kompiliert.

Ich stimme auch der Auffassung zu, dass dieses Problem dem GCC gemeldet werden sollte.

    
Bolero MURAKAMI 04.05.2014, 13:57
quelle
2

Ich kann nur einen Teil Ihrer Frage beantworten, nämlich ob es einen Workaround gibt.

Es gibt: Verwenden Sie eine Helfer constexpr Variable.

Obwohl __builtin_round(__builtin_sqrt(value())) als konstanter Ausdruck abgelehnt wird, wird helper = value() akzeptiert und danach result = __builtin_round(__builtin_sqrt(helper)) . Alternativ helper = __builtin_sqrt(value()) und dann result = __builtin_round(helper) .

Diese Inkonsistenz zeigt, dass GCC eindeutig in der Lage ist, den Ausdruck zur Kompilierzeit zu bewerten und bereit ist, ihn als constexpr zu behandeln. Obwohl es möglicherweise keine Unterstützung im Standard findet, kann es sich als eine Verbesserungsanfrage für den Fehler-Tracker von GCC erweisen.

Aus einem tatsächlichen Grund würde ich raten , dass GCC zuerst einfache konstante Faltung durchführt, dann prüft, ob constexpr zusätzliche konstante Faltung erfordert, und wenn ja, überprüft, ob der Ausdruck mit dem% co_de übereinstimmt % Anforderungen, und wenn ja, berechnet das Ergebnis. Die Überprüfung würde fehlschlagen, da der Ausdruck technisch nicht gültig ist, aber die zusätzliche Hilfsvariable würde die einfache konstante Faltung verbessern, so dass zum Zeitpunkt der Überprüfung der Gültigkeit die ungültigen eingebauten Funktionen nicht mehr vorhanden sind. Aber wie gesagt, es ist eine Vermutung.

    
hvd 03.05.2014 18:35
quelle
1

Dies scheint auf g ++ 4.8.2 zu funktionieren:

%Vor%

Interessanterweise beschwert sich der Compiler, wenn ich roundl durch round ersetze:

%Vor%

Das funktioniert auch:

%Vor%

Aber nochmal, nur mit roundl und nicht mit round . All dies gilt auch, wenn Sie die entsprechenden __builtin_ Versionen verwenden (die diese einfach umbrechen).

Ich lade jetzt die gcc Quelle herunter, um einen Blick darauf zu werfen, habe aber noch keine Antwort auf "warum".

    
Edward 04.05.2014 17:20
quelle