Kompilierzeit-Template-Instanziierungsprüfung

8

Ist es möglich zu überprüfen, ob ein Template-Typ zur Kompilierzeit instanziiert wurde, damit ich diese Informationen in einer enable_if-Spezialisierung verwenden kann?

Sagen wir, ich habe

%Vor%

Kann ich irgendwie einen is_known_type definieren, dessen Wert wahr ist, wenn der bekannte Typ zur Kompilierzeit instanziiert wird?

    
tuccio 27.01.2015, 20:55
quelle

3 Antworten

15

Dies ist möglich, wenn Sie die Tatsache nutzen, dass bestimmte Ausdrücke an Stellen verwendet werden, an denen constexpr s erwartet werden, oder nicht, und dass Sie abfragen können, um zu sehen, welcher Status für jeden Ihrer Kandidaten gilt. Speziell in unserem Fall ist die Tatsache, dass constexpr s ohne Definition nicht als konstante Ausdrücke übergeben werden kann und noexcept ist eine Garantie für konstante Ausdrücke. Daher zeigt noexcept(...) , das true zurückgibt, das Vorhandensein einer richtig definierten constexpr an.

Im Wesentlichen behandelt dies constexpr s als Ja / Nein-Schalter und führt den Status zur Kompilierzeit ein.

Beachten Sie, dass dies ein Hack ist, Sie benötigen Umgehungslösungen für bestimmte Compiler (siehe die folgenden Artikel), und diese spezifische friend -basierte Implementierung könnte von künftigen Versionen des Standards als fehlerhaft angesehen werden.

Mit dem aus dem Weg ...

Filip Roséen präsentiert dieses Konzept in Der Artikel ist speziell diesem Thema gewidmet.

Seine Beispielimplementierung ist mit zitierten Erklärungen:

%Vor%
  

Eine constexpr-Funktion kann in einem von zwei Zuständen sein; Entweder ist es   verwendbar in einem konstanten Ausdruck, oder es ist nicht - wenn es a fehlt   Definition es fällt automatisch in die letztere Kategorie - es gibt keine   anderer Zustand (außer wir betrachten nicht definiertes Verhalten).

     

Normalerweise sollten constexpr-Funktionen genau so behandelt werden, wie sie sind   sind; Funktionen, aber wir können sie auch als individuelle Handles sehen   "Variablen" haben einen ähnlichen Typ wie bool, wo jede "Variable" stehen kann   habe einen von zwei Werten; verwendbar oder nicht verwendbar.

     

In unserem Programm hilft es, wenn Sie die Flagge als genau betrachten; ein Griff   (keine Funktion). Der Grund ist, dass wir nie Flagge nennen werden   In einem evaluierten Kontext interessiert uns nur sein aktueller Zustand.

%Vor%
  

writer ist eine Klassenvorlage, die nach der Instantiierung ein   Definition für eine Funktion in ihrem umgebenden Namensraum (mit dem   Signatur-Int-Flag (Tag), wobei Tag ein Template-Parameter ist.

     

Wenn wir noch einmal an constexpr denken, dass es für einige als Handles fungiert   Variabel können wir eine Instantiierung des Schreibers als   unbedingtes Schreiben des Wertes, der für die Variable hinter dem   Funktion in der Friend-Deklaration.

%Vor%
  

Ich wäre nicht überrascht, wenn Sie denken, dass dependent_writer aussieht wie ein   ziemlich sinnlose Indirektion; warum nicht direkt Schriftsteller instanziieren   wo wir es verwenden wollen, anstatt durch dependent_writer zu gehen?

     
  1. Instantiierung des Schreibers muss von etwas abhängen, um sofortige Instanziierung zu verhindern, und;
  2.   
  3. dependent_writer wird in einem Kontext verwendet, in dem ein Wert vom Typ bool als Abhängigkeit verwendet werden kann.
  4.   
%Vor%
  

Das oben könnte ein bisschen komisch aussehen, aber es ist wirklich ziemlich einfach;

     
  1. setzt B = true, wenn flag (0) ein konstanter Ausdruck ist, andernfalls B = false und;
  2.   
  3. instanziiert instantly_writer (sizeof benötigt einen vollständig definierten Typ).
  4.   

Das Verhalten kann mit dem folgenden Pseudocode ausgedrückt werden:

%Vor%

Endlich, der Proof of Concept:

%Vor%

Ich habe das auf Ihr spezielles Problem angewendet. Die Idee ist, mit den Schaltern constexpr Yes / No anzugeben, ob ein Typ instanziiert wurde. Sie benötigen also einen separaten Schalter für jeden Typ, den Sie haben.

%Vor%

inst_check_wrapper<T> umschließt im Wesentlichen einen Schalter für den Typ, den Sie ihm geben. Es ist nur eine generische Version des ursprünglichen Beispiels.

%Vor%

Der Switch-Toggler ist identisch mit dem im ursprünglichen Beispiel. Es kommt mit der Definition für den Schalter eines Typs, den Sie verwenden. Um eine einfache Überprüfung zu ermöglichen, fügen Sie einen Helper Switch Inspector hinzu:

%Vor%

Schließlich registriert sich der Typ selbst als initialisiert. In meinem Fall:

%Vor%

Der Schalter wird eingeschaltet, sobald dieser spezielle Konstruktor angefordert wird. Beispiel:

%Vor%

Live auf Coliru.

    
user932887 11.05.2015, 18:57
quelle
2

Nein, eine Kompilierzeitprüfung für nicht instanziierte Klassen ist nicht möglich. Sie können jedoch eine (statische) Zuordnung von instanziierten Klassen (im Debug-Build) erstellen, die Sie zur Laufzeit überprüfen können.

Es sollte jedoch möglich sein, die verknüpfte Binärdatei zu analysieren, indem eine Liste erwarteter instanziierter Klassen mit tatsächlich instanziierten Klassen verglichen wird (aber das ist nach der Kompilierzeit und nach meinem Wissen).

    
Dieter Lücking 27.01.2015 21:01
quelle
-1

Es gibt keine Möglichkeit, das zu tun. Also würde ich sagen: Nein.

    
Ralph Tandetzky 27.01.2015 20:59
quelle

Tags und Links