Propagierung von ‚typedef‘ von der Basis abgeleitete Klasse für ‚Vorlage‘
-
10-07-2019 - |
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;
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;