Erzwingt das Auswerten eines konstanten Ausdrucks während der Kompilierzeit?

8

Vor ein paar Tagen habe ich gefragt, nach welchen Kriterien der Compiler entscheidet, ob während der Kompilierzeit eine constexpr-Funktion berechnet wird oder nicht.

Wann wird eine constexpr-Funktion beim Kompilieren ausgewertet? Zeit?

Wie sich herausstellt, wird ein conetexpr nur während der Kompilierzeit ausgewertet, wenn alle Parameter konstante Ausdrücke sind und die Variable, der Sie ihn zuweisen, ebenfalls ein konstanter Ausdruck ist.

%Vor%

Wenn das, was mir gesagt wurde, wahr ist, ist dieses Codebeispiel sehr unpraktisch, da foobar keinen conexpr nimmt (Sie können consexpr aus irgendeinem Grund nicht für Parameter verwenden), POW wird während der Laufzeit ausgewertet, obwohl dies der Fall wäre war es möglich, es während der Kompilierzeit zu berechnen. Die offensichtliche Lösung zum Erzwingen einer Kompilierzeitauswertung wäre dies:

%Vor%

Dies zwingt mich jedoch, eine zusätzliche Codezeile zu verwenden, die nicht jedes Mal notwendig sein sollte, wenn ich sicherstellen möchte, dass ein conexpr während der Kompilierung ausgewertet wird. Um dies ein wenig bequemer zu machen, habe ich das folgende zweifelhafte Makro:

%Vor%

Trotz der Tatsache, dass es gut funktioniert, habe ich das Gefühl, dass etwas nicht stimmt. Wird eine anonyme Lambda-Impact-Leistung erstellt? Wird der Ausdruck tatsächlich durch den Rückgabewert Rvalue auf den Parameter function verschoben? Wie beeinflusst std :: die Schlagleistung? Gibt es dafür eine bessere One-Liner-Lösung?

    
Ansgar Dabs 12.01.2013, 14:29
quelle

1 Antwort

3

Nur um es nicht in Kommentaren begraben zu lassen:

%Vor%

EDIT1:

Ein Vorbehalt bei dieser Methode: constexpr functions können Gleitkommazahlen akzeptieren und constexpr Gleitkommavariablen zugewiesen werden, aber Sie können einen Gleitkommatyp nicht als nicht typisierten Schablonenparameter verwenden. Auch dieselben Einschränkungen für andere Arten von Literalen.

Ihr Lambda würde dafür funktionieren, aber ich denke, dass Sie eine Standard-Erfassung benötigen würden, um eine sinnvolle Fehlermeldung zu erhalten, wenn nicht constexpr sachen an die Funktion übergeben werden. Diese Endung std::move ist entbehrlich.

EDIT2:

Err, Ihr Lambda-Ansatz funktioniert bei mir nicht, ich habe gerade erkannt, wie es überhaupt funktionieren kann, das Lambda ist keine constexpr -Funktion. Es sollte auch nicht für Sie arbeiten.

Es scheint wirklich nicht anders zu sein, als eine constexpr Variable im lokalen Bereich zu initialisieren.

EDIT3:

Oh, ok, mein Schlechter, der Zweck des Lambda ist nur die Bewertung. Also funktioniert es dafür. Sein Ergebnis ist stattdessen, das unbrauchbar ist, einer anderen Kompilierungszeit zu folgen.

EDIT4:

In C ++ 17 kann lambdas jetzt in constexpr -Kontexten verwendet werden, so dass die Beschränkung, auf die in EDIT2 / EDIT3 verwiesen wird, ist entfernt! Also ist die Lambda-Lösung die richtige. Siehe diesen Kommentar für weitere Informationen.

    
pepper_chico 12.01.2013, 19:18
quelle