Wird consteval die Verwendung von static_assert für Funktionsargumente zulassen?

Lesezeit: 3 Minuten

Benutzer-Avatar
KEIN NAME

Derzeit können Sie nicht verwenden static_assert um Parameter von a zu überprüfen constexpr funktionieren, auch wenn alle Anrufe darauf tatsächlich erfolgen constexpr. Das ist sinnvoll, da der Compiler immer noch eine nicht-constexpr-Instanziierung dieser Funktion erstellen muss, falls ein anderes Modul versucht, sie aufzurufen. Leider ist dies der Fall, auch wenn die Funktion ist static oder in einem anonymen Namespace.

C++20 wird jedoch ein neues Schlüsselwort einführen consteval was ist wie constexpr aber es erlaubt nicht, eine Funktion auf eine nicht-constexpr-Weise aufzurufen. In diesem Fall kann der Compiler sicher wissen, dass die Funktionsparameter zur Kompilierzeit immer bekannt sind. Daher sollte es theoretisch möglich sein, sie mit zu validieren static_assert.

Die Frage ist: Lässt die Norm das zu?


Beispiel:

#include <iostream>

consteval char operator""_bchar(const char text[], const size_t length)
{
    static_assert(length == 8, "Binary char has to have 8 digits!"); // <-- This is currently not possible.
    uint8_t byte = 0;
    for (size_t i = 0; i != length; ++i)
    {
        byte <<= 1;
        byte |= text[i] == '1' ? 0b00000001 : 0b00000000;
    }
    return byte;
}

int main()
{
    std::cout << "01000001"_bchar << std::endl;
    return 0;
}

Ich frage, weil ich einige benutzerdefinierte Literale schreiben werde (komplizierter als das Beispiel). Ich habe die Möglichkeit, Compiler-Erweiterungen zu verwenden, um mit der Validierung fertig zu werden, oder ein wenig auf das Compiler-Update zu warten und vollständig standardkonformen Code zu schreiben.

Benutzer-Avatar
Barry

Wird consteval die Verwendung von static_assert für Funktionsargumente erlauben?

Nein. Funktionsargumente waren und sind nie als konstante Ausdrücke verwendbar.

Es gibt einen Unterschied zwischen etwas, das konstant ausgewertet wird und als konstanter Ausdruck verwendbar ist. consteval stellt sicher, dass wir uns in einem ständigen Bewertungskontext befinden, aber es führt auch nicht dazu, dass alles zu konstanten Ausdrücken wird.

Damit Funktionsargumente als konstante Ausdrücke verwendet werden können, müssten Sie alles implizit zu einer Vorlage machen:

template <int> struct X { };

consteval auto foo(int i) {
    static_assert(i > 10); // in order to allow this...
    return X<i>{};         // ... you'd have to allow this too
}

Und nun foo(20) und foo(30) verschiedene Typen zurückgeben. Das ist eine Vorlage.


Wichtige Hintergrundinformationen zum Verständnis, warum dies eine grundlegende und inhärente Einschränkung ist, finden Sie in Andrew Suttons Übersetzung und Auswertung: Ein mentales Modell für die Metaprogrammierung zur Kompilierzeit:

Ein mentales Modell der Kompilierzeitbewertung zu haben, das sie physisch vom Übersetzungsprozess trennt, war für mich äußerst hilfreich. Insbesondere hat es mir geholfen zu verstehen, was nicht möglich ist (z. B. das Instanziieren einer Vorlage während der Evaluierung). Dies hilft dabei, den Designbereich für ansonsten große und komplexe Sprachfeatures zu beschneiden. Hoffentlich finden auch andere diesen Hinweis hilfreich.


Mit static_assert Insbesondere können Sie jedoch eine Problemumgehung hinzufügen, um einen Kompilierungsfehler zu verursachen. Das ist nur das Hinzufügen von allem, was während der ständigen Bewertung nicht verwendet werden kann. Wie:

#define CONSTEVAL_STATIC_ASSERT(c, msg) do { if (!(c)) throw msg; } while(false)

wie in:

consteval char operator""_bchar(const char text[], const size_t length)
{
    CONSTEVAL_STATIC_ASSERT(length == 8, "Binary char has to have 8 digits!");
    // ...
}

  • Dein CONSTEVAL_STATIC_ASSERT schlägt zur Kompilierzeit nicht fehl. Es löst die Ausnahme zur Laufzeit aus. ich benutze g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0.

    – KEIN NAME

    26. Juli 2019 um 20:58 Uhr

  • Egal, es funktioniert, wenn ich versuche, es einer constexpr-Konstante zuzuweisen.

    – KEIN NAME

    26. Juli 2019 um 21:05 Uhr


  • There is a difference between something being constant evaluated and being usable as a constant-expression. Was ist der Unterschied?

    – KEIN NAME

    26. Juli 2019 um 21:09 Uhr

  • @NO_NAME Das ist es schon X<i> das ist das Problem. Und ja, Ersteres zuzulassen bedeutet zwangsläufig, Letzteres zuzulassen.

    – Barri

    26. Juli 2019 um 21:36 Uhr

  • Hmm, ich nehme an, dass Consteval-Funktionen bereits erforderlich sind, damit ihr Code zur Anrufzeit vorhanden ist. Was ist also das Problem, sie implizit zu Vorlagen zu machen?

    – Johannes Schaub – litb

    4. August 2019 um 12:16 Uhr

1018990cookie-checkWird consteval die Verwendung von static_assert für Funktionsargumente zulassen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy