Frage

Ich versuche Basisklasse zu definieren, die typedef ist nur enthält.

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
private:
    Vec_t v;  // fails - Vec_t is not recognized
};

Warum in B erhalte ich einen Fehler, dass vec_t nicht erkannt wird und ich brauche es explizit zu schreiben?

typename A<T>::Vec_t v;
War es hilfreich?

Lösung

Ich glaube, dass diese Frage ist doppelt, aber ich kann es jetzt nicht finden. C ++ Standard besagt, dass Sie sich voll Namen nach 14.6.2 / 3 qualifizieren sollen:

  

In der Definition einer Klasse-Vorlage oder ein Mitglied einer Klasse-Vorlage, wenn eine Basisklasse der Klassenvorlage auf einem Template-Parametern abhängig ist, die Basisklasse Umfang nicht während unqualifizierter Namenssuche untersucht entweder am Punkt der Definition der Klassenvorlage oder Mitglieds oder während einer Instantiierung der Klassenvorlage oder Mitglieds.

UPD: Ich fand Duplikat schließlich: hier ist es .

Andere Tipps

Es ist etwas genannt abhängig und nondependent Namen bei Vorlagen.

Wenn der Name auf Template-Parameter T hängt seine abhängig Namen und andere diejenigen, hängen nicht von Parametern T sind unabhängig Namen.

  

Hier ist die Regel: der Compiler nicht   Blick in den abhängigen Basisklassen (wie   A) beim Nachschlagen nondependent   Namen (wie vec_t). Als Ergebnis,   der Compiler nicht wissen, dass sie nicht einmal   allein sind Typen existieren lassen.

Compiler kann nicht, dass Vec_t nehmen ist eine Art, bis es T weiß, weil es eine mögliche Spezialisierung von A<T> ist, wo A<T>:: Vec_t ist ein Datenelement ist

So ist die Lösung ist die Verwendung Typname

 typename A<T>::Vec_t v;  ← good

Ich empfehle Ihnen dieses https://isocpp.org/ wiki / faq / templates # nondependent-name-Lookup-Typen .

Alt (gebrochen) Link: http: // www. parashift.com/c++-faq-lite/templates.html#faq-35.18

Da die Compiler, dass Vec_t Namen eine Art nicht sicher sind. Zum Beispiel A<T> für T=int auf spezialisiert werden möglicherweise nicht haben, dass bestimmte typedef.

Der Vollständigkeit halber ist hier, wie Sie dieses Ärgernis ein wenig mildern könnte, entweder:

  • re-typedef dieser Typen in abgeleiteten Klassen, oder besser - wie bei Methoden -
  • importieren nur diese Namen in der abgeleiteten Klasse Rahmen mit einem using declaration:

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

private:
    Vec_t v;
};

Es kann nützlich sein, wenn Sie mehr als eine Erwähnung des geerbten typedef in der abgeleiteten Klasse. Auch brauchen Sie nicht typename jedes Mal mit dieser hinzuzufügen.

Sie müssen explizit die Verwendung von Vec_t zu qualifizieren, da der Compiler nicht weiß, wo Vec_t herkommt.

Es kann nichts über die Struktur von A übernehmen, da kann die Klassenvorlage A spezialisiert sein. Die Spezialisierung kann eine Vec_t enthalten, die kein typedef ist, oder es kann nicht einmal ein Mitglied Vec_t überhaupt gehört.

vec_t ist kein abhängiger Name, und der Compiler muss wissen, was es ohne Instanziierung alle Vorlagen (Basisklasse in diesem Fall) ist. Es ist wirklich nicht anders aus:

template <class T>
class X
{
    std::string s;
}

Auch hier ist der Compiler muss über std :: string wissen, auch wenn X nicht instanziert wird, da der Name auf dem Template-Argument nicht davon abhängt, T (soweit der Compiler annehmen kann).

Alles in allem typedefs in einer Vorlage Basisklasse scheint eher unbrauchbar für den Einsatz in abgeleiteten Klasse. Die typedefs sind nützlich für den Anwender jedoch.

Dieses Konzept kann mit in Verbindung gebracht werden, wie wir std::vector<T> verwenden. Zum Beispiel, wenn wir ein std::vector<int> Foo. Jetzt entscheiden wir, ist Arten Mitglied irgendetwas davon zu verwenden, lässt einen iterator sagen. In diesem Szenario nennen wir explizit

std::vector<int>::iterator foo_iterator;

Ähnlich ist es in Ihrem Fall um eine öffentliche Elementtyp Vec_t von template <typename T> class A zu verwenden, müssen Sie es explizit deklarieren

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top