Constexpr-Zähler, der unter GCC 8 funktioniert und nicht auf den Namespace-Bereich beschränkt ist

HolyBlackCat

Ich versuche, einige arkane Stateful Template-Metaprogrammierungstricks zu lernen .
(Deshalb möchte ich es lernen. Leider funktioniert diese Bibliothek weder mit GCC 8 noch mit Clang.)

Das erste, was ich brauche, ist ein constexprZähler:

/*something*/ constexpr int foo() /*something*/

int main()
{
    constexpr int a = foo();
    constexpr int b = foo();
    constexpr int c = foo();
    static_assert(a == 0 && b == 1 && c == 2);
}

Vorzugsweise sollte es ein markierter Zähler sein, damit ich mehrere Zähler gleichzeitig haben kann:

/*something*/ constexpr int foo() /*something*/

struct TagA {};
struct TagB {};

int main()
{
    constexpr int a = foo<TagA>();
    constexpr int b = foo<TagA>();
    constexpr int c = foo<TagA>();

    constexpr int d = foo<TagB>();
    constexpr int e = foo<TagB>();
    constexpr int f = foo<TagB>();

    static_assert(a == 0 && b == 1 && c == 2);
    static_assert(d == 0 && e == 1 && f == 2);
}

Ich habe einige Nachforschungen angestellt, aber leider funktionierte keiner der Zähler, die ich gefunden habe, mit GCC 8.

Ich habe hier auch einige Implementierungen gefunden: Unterstützt C ++ Zähler für die Kompilierungszeit? Die meisten von ihnen sind jedoch auf den Namespace-Bereich beschränkt, andere funktionieren wiederum nicht mit GCC 8.

Was ich gefunden habe , war eine einfache, durch Proof-of-Concept einstellbare Constexpr-Flagge: http://b.atch.se/posts/non-constant-constant-expressions/

/*something*/ constexpr bool foo() /*something*/

constexpr bool a = foo();
constexpr bool b = foo();
constexpr bool c = foo();
static_assert (a == 0 && b == 1 && c == 1);

Dieser ist nicht markiert, dh Sie können nur einen pro Übersetzungseinheit haben, was nicht gut ist.

Ich habe es geschafft, meine eigene getaggte Implementierung basierend darauf zu schreiben:

Verwendung:

int main()
{
    constexpr int c0_false = Meta::Flag<TagA>::ReadSet();
    constexpr int c0_true  = Meta::Flag<TagA>::ReadSet(); // Will continue to return true after this point.
    static_assert(c0_false == 0);
    static_assert(c0_true  == 1);

    constexpr int c1_false = Meta::Flag<TagB>::ReadSet();
    constexpr int c1_true  = Meta::Flag<TagB>::ReadSet(); // Will continue to return true after this point.
    static_assert(c1_false == 0);
    static_assert(c1_true  == 1);
}

Implementierung:

namespace Meta
{
    template <typename T> class Flag
    {
        struct Dummy
        {
            constexpr Dummy() {}
            friend constexpr void adl_flag(Dummy);
        };

        template <bool> struct Writer
        {
            friend constexpr void adl_flag(Dummy) {}
        };

        template <class Dummy, int = (adl_flag(Dummy{}),0)>
        static constexpr bool Check(int)
        {
            return true;
        }

        template <class Dummy>
        static constexpr bool Check(short)
        {
            return false;
        }

      public:
        template <class Dummy = Dummy, bool Value = Check<Dummy>(0), int = sizeof(Writer<Value && 0>)>
        static constexpr int ReadSet()
        {
            return Value;
        }

        template <class Dummy = Dummy, bool Value = Check<Dummy>(0)>
        static constexpr int Read()
        {
            return Value;
        }
    };
}

(Probieren Sie es live aus.)

Als nächstes habe ich versucht, einen tatsächlichen Zähler zu erstellen.

Gewünschte Verwendung:

constexpr int c0 = Meta::TaggedCounter<TagA>::Value();
constexpr int c1 = Meta::TaggedCounter<TagA>::Value();
constexpr int c2 = Meta::TaggedCounter<TagA>::Value();
static_assert(c0 == 0);
static_assert(c1 == 1);
static_assert(c2 == 2);

Mein naiver Versuch: (Aus irgendeinem Grund hört es bei auf 1.)

namespace Meta
{
    template <typename T> class TaggedCounter
    {
        template <int I> struct Tag {};

      public:
        template <int N = 0, bool B = Flag<Tag<N>>::ReadSet()> static constexpr int Value()
        {
            if constexpr (B)
                return 1 + Value<N+1>();
            else
                return 0;
        }
    };
}

(Probieren Sie es live aus.)

Wie kann ich es reparieren?

Anthony Williams

Der Hauptteil einer constexpr-Funktionsvorlage muss für alle Instatationen mit denselben Vorlagenparametern und denselben Argumenten dieselbe Antwort liefern. Sie müssen eine Indirektionsebene hinzufügen, damit die Berechnung im Standardargument eines Vorlagenparameters erfolgen kann, das vom ersten abhängig ist.

Siehe https://gcc.godbolt.org/z/GHfKKf

namespace Meta
{
    template <typename T,int I> struct Tag {};

    template<typename T,int N,bool B>
    struct Checker{
        static constexpr int currentval() noexcept{
            return N;
        }
    };

    template<typename T,int N>
    struct CheckerWrapper{
        template<bool B=Flag<Tag<T,N>>::Read(),int M=Checker<T,N,B>::currentval()>
        static constexpr int currentval(){
            return M;
        }
    };

    template<typename T,int N>
    struct Checker<T,N,true>{
        template<int M=CheckerWrapper<T,N+1>::currentval()>
        static constexpr int currentval() noexcept{
            return M;
        }
    };

    template<typename T,int N,bool B=Flag<Tag<T,N>>::ReadSet()>
    struct Next{
        static constexpr int value() noexcept{
            return N;
        }
    };

    template <typename T> class TaggedCounter
    {
      public:
        template <int N=CheckerWrapper<T,0>::currentval()> static constexpr int Value(){
            return Next<T,N>::value();
        }
    };
}

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel

Das Bild ist nicht auf einen direkten Bereich beschränkt ist

Gibt es einen Gleitkommatyp, der in Swift auf einen Bereich von 0 bis 1 beschränkt ist?

Der Typ 'Fehler' ist auf den Nichtprotokolltyp beschränkt, auch wenn der Typ ein Protokoll ist

Excel benannter Bereich, der auf Arbeitsmappe beschränkt ist, um einen aus einem Blatt mit benanntem Bereich zu drucken

Protokollerweiterungen in Structs verursachen den Kompilierungsfehler 'Self', der auf den Nichtprotokolltyp beschränkt ist

R shiny beschränkt fileInput auf das Dateinamenmuster und nicht nur auf den Dateityp

Was bedeutet es, dass die Verwendung der Groovy-Kategorie auf den aktuellen Thread beschränkt ist?

Regex in der xsd-Zusicherung ist auf den Anfang des Elementwerts beschränkt

F #, Deedle: Generischer Frame, der auf den Typ Frame <obj, obj> beschränkt ist

xmlNodeList ist nicht auf ausgewählte Knoten beschränkt und bietet keinen korrekten übergeordneten Knoten

Ziehen und Ablegen von eckigem Material cdkDragConstrainPosition ist nicht auf die Komponente beschränkt

Konfliktmethode, wenn der Parameter in Scala auf AnyRef und AnyVal beschränkt ist

Wie erstelle ich Benutzer / Gruppen, die auf den Namespace in Kubernetes beschränkt sind, mithilfe der RBAC-API?

Der Importbereich in Googlesheets ist auf 60 Spalten beschränkt?

Der Zugriff ist auf die Hosts-Datei beschränkt

Typoskript-Mixin beschränkt auf den Typ der Klasse

"NameError: Name 'Zähler' ist nicht definiert" auf Jupyter Notebook, funktioniert aber gut auf PyCharm?

Ist der Indexer von Ecplise CDT auf die gängigen Dateitypen für Quellen und Header beschränkt?

wie man den <inpu type="text"> eingegebenen Wert mit der Direktive auf nicht mehr als 10 beschränkt

Wie beschränke ich den ziehbaren Bereich? Es funktioniert oben und links, aber nicht rechts und unten

Python beschränkt sich auf einen Bereich

Die Überladung der Vorlagenfunktion "operator +" kann mit "enable_if" und "is_base_of" nicht auf meine Klassenhierarchie beschränkt werden

WebStorm beschränkt den Refactor-Bereich nur auf die aktuelle Datei

Azure beschränkt den Zugriff auf Webanwendungen nach IP-Bereich

Ist es möglich, den Bereich basierend auf der angegebenen Koordinate und Bildschirmgröße zu berechnen?

Aktualisieren der JLabel-Textausgabe für den Zähler funktioniert nicht

Der Zähler für den Countdown-Timer funktioniert nicht

Der Namespace 'Eventing' ist in 'System.Diagnostics' in .NET Core und Mono unter nix * es nicht vorhanden

Wenn die Funktionsvorlage auf einen anderen Namespace spezialisiert ist, stimmen GCC und Clang nicht überein

TOP Liste

  1. 1

    Modbus Python Schneider PM5300

  2. 2

    Glassfish v3.0.1 im Vergleich zu Oracle GlassFish Server 3.0.1 - Gibt es einen technischen Grund, die kommerzielle Version zu verwenden?

  3. 3

    Wie schließe ich mehrere Ordner mit der Variablen EXTRA_ARGS aus?

  4. 4

    Wie kann eine gleichmäßige Lastverteilung in ElasticSearch mit Indizes mit unterschiedlicher Anzahl von Shards erreicht werden?

  5. 5

    Wie kann man eine Multi-Container-Anwendung in Steuerkarten erstellen?

  6. 6

    ElasticSearch - Knotensperren konnten nicht abgerufen werden

  7. 7

    Python: Spalten mit demselben Namen zusammenführen, wobei der Mindestwert beibehalten wird

  8. 8

    Elasticsearch startet nicht nach dem Laden in viele Daten

  9. 9

    Ärgerliches Problem mit yaml, das ich nicht lösen kann

  10. 10

    Wie Verwenden von Httpclient mit jedem SSL-Zertifikat, egal wie „schlecht“ es ist

  11. 11

    Wie vergleicht man scala.xml-Knoten richtig?

  12. 12

    ElasticSeach Auto Complete mit dem Vervollständigungsvorschlag, um das vollständige Dokument zurückzugeben

  13. 13

    Wie füge ich eine Spalte in einer Zeile in der Ansible Jinja2-Vorlage mit der for-Schleife hinzu?

  14. 14

    HTTPS-Verbindung mit Moneris-Servern in Curl

  15. 15

    Unity Build-Fehler: Der Name 'EditorUtility' ist im aktuellen Kontext nicht vorhanden

  16. 16

    Bester Crawler, um festzustellen, ob er mit Technologien gebaut wurde?

  17. 17

    So erhalten Sie eine gleichmäßige Höhe für alle Eingabefelder

  18. 18

    Wie kann ich den Kaskadenmodus global einstellen?

  19. 19

    Eclipse Oxygen - Projekte verschwinden

  20. 20

    Wie konvertiere ich einen Vektor von Bytes (u8) in eine Zeichenfolge?

  21. 21

    ElasticSearch BulkShardRequest ist aufgrund von org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor fehlgeschlagen

heißlabel

Archiv