CRTP – Zugriff auf unvollständige Typmitglieder

Lesezeit: 2 Minuten

Benutzer-Avatar
DimG

Verwandte Fragen: eins, zwei

Nachdem ich mehrere Tage lang versucht habe, CRTP zu verstehen, verstehe ich jetzt anscheinend noch weniger als zuvor 🙂

Betrachten Sie den folgenden Code:

01 #include <iostream>
02 
03 template <class IMPL>
04 class Interace
05 {
06 public:
07     typedef typename IMPL::TYPE TYPE;  // ERROR: "...invalid use of incomplete type..."
08     void foo() { IMPL::impl(); }       // then why does this work?
09 };
10 
11 class Implementation : public Interface<Implementation>
12 {
13 public:
14    typedef int TYPE;
15    static void impl() { std::cout << "impl() " << std::endl; }
16 };
17 
18 
19 int main()
20 {
21     Implementation obj;
22     obj.foo();
23 }

Die Fragen sind:

  1. Warum kann ich Funktion aus aufrufen IMPL:: (Zeile 8), kann aber nicht auf Typdateien zugreifen (Zeile 7)? In der verwandten Frage heißt es IMPL ist an dieser Stelle ein unvollständiger Typ. Aber warum ist dann Zeile 8 richtig?

  2. Was ist die Reihenfolge der Typdeklaration/Definition? Wie ich es sehe:

    a. Interface Vorlage – OK. Bringt bis zur Instanziierung keine Probleme

    b. Zeile 11 — danach class ImplementationImplementation Typ deklariert, aber nicht definiert.

    c. Zeile 11 — danach Interface<Implementation> — Template-Instanziierung. An diesem Punkt Implementation ist aufgrund von Schritt (b) bereits bekannt (aber nicht definiert!). Compiler “injiziert” Code mit IMPL Ersetzt mit Implementation. Hier sind aus meiner Sicht weder Zeile 7 noch Zeile 8 nicht legal, da der Compiler das zu diesem Zeitpunkt noch nicht weiß Implementation hat diese Mitglieder. Woher weiß es als?

Oder geht Instanziierung vielleicht wirklich in Zeile 21? Aber warum funktioniert in diesem Fall die Zeile 07 nicht?

Ich denke mehr darüber nach, weniger Verständnis für die Grundlagen von C++, die ich habe. Jede Klarstellung wird geschätzt.

Wenn eine Klassenvorlage instanziiert wird, werden ihre Mitglieder außer nicht virtuellen Memberfunktionen zusammen mit ihr instanziiert. Nicht-virtuelle Elementfunktionen werden jedoch nur dann instanziiert, wenn sie von odr verwendet werden (im Grunde werden sie aufgerufen oder ihre Adresse wird genommen).

Wenn der Compiler trifft class Implementation : public Interface<Implementation>muss es instanziiert werden Interface<Implementation>. An diesem Punkt, Implementation ist noch ein unvollständiger Typ, seine TYPE Mitglied wurde noch nicht gesehen. Auf der anderen Seite, Interface<Implementation>::foo wird erst später instanziiert, wenn es aufgerufen wird main. An diesem Punkt, Implementation ist ein vollständiger Typ.

  • Übergeben Sie einen zusätzlichen Parameter an Interfacewie in Implementation : public Interface<Implementation, int>. Haben Interface Typdef TYPE von diesem Parameter, dann Implementation bräuchte es nicht.

    – Igor Tandetnik

    4. November 2020 um 2:04 Uhr

1012580cookie-checkCRTP – Zugriff auf unvollständige Typmitglieder

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

Privacy policy