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:
__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 ... value()
durch ein Literal 1.23
ersetzt wird, wird auch der Fehler entfernt. __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 ++.
Ich habe eine Idee von einer anderen Problemumgehung.
Es gibt: Verwenden Sie eine Hilfsfunktion pass_through
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.
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.
Dies scheint auf g ++ 4.8.2 zu funktionieren:
%Vor% Interessanterweise beschwert sich der Compiler, wenn ich roundl
durch round
ersetze:
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".
Tags und Links c++ g++ floating-point constexpr builtin