Wie kann diese Methode constepxr sein?



  • Hallo Leuts,

    Ich implementiere gerade die string_view-Klasse, welche in C++17 eingeführt wird.
    Dabei bin ich über folgende Methode gestolpert.

    http://en.cppreference.com/w/cpp/experimental/basic_string_view/remove_suffix

    constexpr void remove_suffix(size_type n);
    

    Diese ist constexpr, was mich irritiert, denn es bedeutet, dass ich constexpr wohl falsch verstanden habe oder eine Erweiterung eingebracht wurde, welche mir entging. Diese Methode ändert offensichtlich den inneren Zustand des Objekts, da der Iterator, welcher auf das Ende zeigt, nach vorne verschoben wird. Wie aber kann das sein?
    Soweit ich das bisher verstanden habe impliziert der der Aufruf einer Methode zur Kompilierungszeit, dass das Objekt zuvor ebenfalls während der Kompilierung erstellt wurde. Das Objekt ist also selbst constexpr. Damit müsste doch das Ändern von Membervariablen untersagt sein. Wo ist mein Denkfehler?

    MFG

    Martin



  • Meines Wissens:

    constexpr -Funktionen können auch zur Laufzeit ausgewertet werden, wenn dies der Kontext zur Compile-Zeit nicht erlaubt.
    Bei dieser Methode wäre das z.B. der Fall wenn das Argument kein Literal oder constexpr -Ausdruck ist, oder die Methode
    nicht innerhalb einer anderen constexpr -Funktion aufgerufen wird.

    Soweit ich weiss besagt das constexpr hier nur, dass die Methode alle Anforderungen erfüllt, die an eine constexpr -Funktion
    gestellt werden. Das bedeutet, dass diese Funktion innerhalb einer anderen constexpr -Funktion aufgerufen werden kann, in
    der man sich z.B. einen speziellen constexpr -String-View auf einen konstanten String zusammenstrickt.

    Die aktuellen Regeln für constexpr erlauben soweit ich informiert bin tatsächlich, dass diese z.B. eine Member-Variable verändern
    dürfen. Hier die entsprechende Funktion aus der libc++-Implementierung von basic_string_view ( __size ist Member-Variable):

    _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
    void remove_suffix(size_type __n) _NOEXCEPT
    {
        _LIBCPP_ASSERT(__n <= size(), "remove_suffix() can't remove more than size()");
        __size -= __n;
    }
    

    Ausserhalb eines constexpr -Kontextes scheint diese Methode wohl genau das zu tun, was sie auch ohne constexpr machen würde.
    Innerhalb eines constexpr -Kontextes wird sie dann wenn möglich vom Compiler ausgeführt um den __size -Member eines compile-time-
    konstanten basic_string_view zu berechnen.

    Gruss,
    Finnegan


  • Mod

    Finnegan schrieb:

    Meines Wissens:

    constexpr -Funktionen können auch zur Laufzeit ausgewertet werden, wenn dies der Kontext zur Compile-Zeit nicht erlaubt.

    Korrekter wäre: constexpr Funktionen werden nur garantiert zur Compilezeit ausgeführt, wenn der Kontext es verlangt. Deine Aussage suggeriert, dass die Funktion zur Compilezeit ausgeführt wird, wenn das möglich ist; das stimmt nicht, und würde auch Probleme bzgl. Einheitlichkeit mit sich bringen.

    Die aktuellen Regeln für constexpr erlauben soweit ich informiert bin tatsächlich, dass diese z.B. eine Member-Variable verändern
    dürfen.

    Ich will nicht arrogant rüberkommen, aber es kann ja wohl nicht sein, dass in einem C++-Forum drei Jahre nach Einführung eines Features (was mittlerweile im Sprachstandard steht) noch keiner sicher über solche Dinge ist. Wo sind die ganzen versierten Sprachtheoretiker?


  • Mod

    Martin Kalbfuß schrieb:

    Damit müsste doch das Ändern von Membervariablen untersagt sein.

    Jo. Siehe bspw. meine constexpr string Implementierung: https://github.com/Arcoth/Constainer/blob/master/String.hxx



  • Zur Info nochmal an alle.

    Danke für eure Antworten. Vor allem Arcoth. Ich habe ich jetzt noch mal auf Basis eurer Informationen schlau gemacht. Dabei ist mir aufgefallen, dass ich einer Falschaussage auf den Leim gegangen bin und deshalb ein falsches Verständnis von constexpr hatte. Diese lautete sinngemäß:

    "Eine constepxr Funktion wird dann zur Kompilierungszeit ausgeführt, wenn alle Argumente ebenfalls zur Kompilierungszeit feststehen."

    Das ist nicht korrekt!

    Korrekt ist, dass eine constexpr Funktion zur Kompilierungszeit ausgeführt wird, wenn es in einem Konstanten Ausdruck verwendet wird. Nur dann ist garantiert, dass sie zur Kompilierungszeit ausgeführt wird. Alles andere obliegt der Kompilerimplementierung.

    MFG

    Martin


Log in to reply