Ist zustandsbehaftete Metaprogrammierung (noch) unausgereift?

Lesezeit: 4 Minuten

Benutzer-Avatar
Passant vorbei

Eine meiner geliebtesten/bösartigsten Erfindungen, auf die ich das Glück hatte, zu stoßen, ist die constexpr-Zähler, auch bekannt als zustandsbehaftete Metaprogrammierung. Wie im Beitrag erwähnt, scheint es unter C ++ 14 legal zu sein, und ich frage mich, ob sich mit C ++ 17 etwas geändert hat.

Das Folgende ist eine Implementierung, die weitgehend auf der Post basiert

template <int N>
struct flag
{
    friend constexpr int adl_flag(flag<N>);
    constexpr operator int() { return N; }
};

template <int N>
struct write
{
    friend constexpr int adl_flag(flag<N>) { return N; }
    static constexpr int value = N;
};

template <int N, int = adl_flag(flag<N>{})>
constexpr int read(int, flag<N>, int R = read(0, flag<N + 1>{}))
{
    return R;
}

template <int N>
constexpr int read(float, flag<N>)
{
    return N;
}

template <int N = 0>
constexpr int counter(int R = write<read(0, flag<0>{}) + N>::value)
{
    return R;
}

Und wir benutze es als

static_assert(counter() != counter(), "Your compiler is mad at you"); 

template<int = counter()>
struct S {};

static_assert(!std::is_same_v<S<>, S<>>, "This is ridiculous");

Ist dies übrigens ein direkter Widerspruch zum Speichern von Zuständen in der C++-Metaprogrammierung?

  • Wie funktioniert read(0, flag<N + 1>{}) führt nicht zu einer Endlosschleife? Das Literal 0 bewirkt, dass die erste Überladung aufgerufen wird (int gegenüber bevorzugt werden float), die es natürlich immer und immer wieder aufrufen wird. Was ist die Beendigungsbedingung?

    – Nicol Bolas

    30. Mai 2017 um 16:56 Uhr


  • @NicolBolas Von SFINAE, der int Überlastung von read(0, flag<N + 1>{}) kann nicht für einige groß genug aufgerufen werden N da wir noch nicht definiert haben adl_flag(flag<N + 1>)deshalb, die float Überladung würde aufgerufen werden. Für die vollständige Erklärung ist der verlinkte Beitrag hervorragend geschrieben.

    – Passant

    30. Mai 2017 um 16:58 Uhr


  • Beachten Sie auch die Mängel, auf die David Krauss im entsprechenden hinwies std-Diskussion Thread, den Filip versprochen hat, in einem vierten Beitrag anzusprechen, es aber nie getan hat.

    – Kolumbus

    30. Mai 2017 um 17:30 Uhr

  • Das ist schrecklich, ich liebe es!

    – Mark K. Cowan

    30. Mai 2017 um 23:50 Uhr

  • Muss der Compiler tatsächlich jedes Mal, wenn die Vorlage verwendet wird, einen Standardvorlagenparameter neu auswerten (ohne diesen Parameter anzugeben)?

    – Gebührensumme

    31. Mai 2017 um 16:24 Uhr

Benutzer-Avatar
Barry

Das ist CWG aktive Ausgabe 2118:

Das Definieren einer Friend-Funktion in einer Vorlage und das spätere Referenzieren dieser Funktion bietet ein Mittel zum Erfassen und Abrufen des Metaprogrammierungsstatus. Diese Technik ist geheimnisvoll und sollte unausgegoren gemacht werden.

Notizen vom Treffen im Mai 2015:

CWG stimmte zu, dass solche Techniken schlecht formuliert sein sollten, obwohl der Mechanismus, sie zu verbieten, noch unbestimmt ist.

Es ist immer noch ein aktives Problem, an C++17 wird sich zumindest vorerst nichts ändern. Wenn jedoch ein solcher Verbotsmechanismus festgestellt wird, kann dies rückwirkend als DR entschieden werden.

  • Ist “diese Technik geheimnisvoll (dh von wenigen verstanden, mysteriös, geheim)” wirklich, dass es “falsch geformt sein sollte”? Viele der Standard C++-Idiome haben wir heute im Wesentlichen auf diese Weise begonnen (TMP, CRTP, ADL, um nur einige zu nennen).

    – Andi G

    11. Mai 2019 um 8:36 Uhr

  • Bedeutet dies, dass die Verwendung einer Friend-Funktion in einer Vorlage und späterer Verweis darauf verboten ist, selbst wenn sie nicht zum Erfassen des Metaprogrammierungsstatus verwendet wird? Dies kann verwendet werden, um zugeordnete Klassen zu ADL hinzuzufügen, wie hier. Dies scheint keine zustandsbehaftete Metaprogrammierung zu sein, obwohl es auf demselben Mechanismus beruht.

    – Paul FultzII

    23. Februar um 23:08 Uhr

  • @PaulFultzII Ich denke, das stimmt mehr oder weniger genau mit der Problembeschreibung überein? Ansonsten weiß ich nicht mehr als das, was in der Ausgabe steht. In den letzten, soweit ich weiß, fast 5 Jahren hat sich diesbezüglich nichts getan.

    – Barri

    23. Februar um 23:17 Uhr

  • @AndyG: Dieser ist anders, weil er das Sprachmodell bricht – bedenken Sie, wie bedeutungslos die ODR ist, wenn verschiedene Definitionen einer Vorlage unterschiedliche Werte von einem solchen Zähler sehen.

    – Davis Hering

    24. Februar um 3:38 Uhr

  • @DavisHerring: Ich bin jedoch gespannt, wie sie dies schlecht formulieren werden. Es gibt bessere und “unterstütztere” Mechanismen zum Durchführen der zustandsbehafteten Metaprogrammierung als die in der ursprünglichen Frage verwendeten Mechanismen, die C++ 20-Funktionen nutzen. Compiler müssten tatsächlich eine schlechte Verwendung erkennen und diese Verwendung speziell blockieren, während sie die als akzeptabel erachtete Verwendung durchlassen. Ich bin mir nicht sicher, ob das möglich ist! Besser ist, dass jemand eine Boost-Bibliothek erstellt, die diese zustandsbehafteten Metaprogrammierungsfunktionen verwendet, dann wird sie zu einer erstklassigen Funktion der Sprache!

    – Andi G

    1. März um 16:19 Uhr

1013340cookie-checkIst zustandsbehaftete Metaprogrammierung (noch) unausgereift?

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

Privacy policy