TL; DR: Sie versuchen einen Typalias durch Makrosubstitution. Das ist immer riskant. Die Lösung besteht darin, das Makro with a using
declaration zu ersetzen.Zum Beispiel
using myBigInteger = long long int;
Allgemeine Form:
using <alias> = <data type>
Kompliziertere Beispiele:
using datavector = std::vector<int32_t>; // a vector of 32 bit ints
using dataiterator = datavector::iterator; // and iterator of a vector of 32 bit ints
using functionpointer = void (*)(dataiterator begin, dataiterator end);
// a pointer to a function that does something to the specified iterator range
Die oben gibt gute One-Stop-Ort, um die Art der möglicherweise Tausende von Stellen im Code ändern wo std::vector<int32_t>
in std::vector<double>
geändert werden muss, aber ein einfacher finden und ersetzen wird nicht tun, weil nur einige der std::vector<int32_t>
s, die vector
s voller Daten, muss geändert werden.
Nächstes verwenden Sie nicht typename
using type = typename;
Dies wird genauso schlecht ausfallen, aber anders, weil Typname ein reservierter Begriff mit besonderen Bedeutungen kontextabhängig ist. Normalerweise würden Sie etwas entlang der Linien von
error: ‘typename’ does not name a type
Aber in diesem Fall Typname wird verwendet, um declare dependent, nested, naming, so dass der schlechte Compiler geht der Suche nach dieser Verschachtelung erwarten und kann es nicht finden. Eine Komödie von Fehlermeldungen kann folgen.
Lange Version und warum das angegebene Codebeispiel fehlschlägt:
Zuerst ein wenig hilfreichen Lesung: How does the compilation/linking process work?
Vor dem Kompilieren des C++ Präprozessor (und der C-Präprozessor für diese Angelegenheit) beginnt machen eine umfangreiche Datei der C++ - Quelldatei und alle darin enthaltenen Header. Gleichzeitig führt der Prozessor eine Textersetzung von Tokens durch, für die eine Substitution definiert wurde. Dies bedeutet, dass jedes Mal, wenn das Token type
gefunden wird, es durch das Token typename
ersetzt wird. Es spielt keine Rolle, welche Datei enthält type
nach
#define type typename
gefunden wird. Alle Instanzen von type
werden in Ihren Dateien, den Standardbibliotheksheadern, Drittanbieterheadern, alles ersetzt, da es sich jetzt um eine einzige große Datei handelt.
Nachdem der Präprozessor das Sammeln und Konvertieren aller erforderlichen Komponenten abgeschlossen hat, wird der Compiler auf dieser einen großen Datei ausgeführt. In diesem Fall findet es den reservierten Term typename
verstreut durch die Datei an Stellen, die absolut keinen Sinn machen und es dementsprechend Fehlermeldungen ausspuckt. In diesem Fall, während typename
schlecht ist, ist praktisch jeder Name schlecht, weil die Textersetzung absolut sinnlos ist. Es ist egal, wie der Token verwendet wird. Das Token wird ersetzt.
#define type fubar
wird Kennung type
zu fubar
umbenennen, die bereits mit anderen Bezeichnern in Konflikt stehen könnten fubar
benannt. Die Leser des Codes werden keine Ahnung haben, was vor sich geht. Ich habe mich einmal selbst in den Fuß mit einer Variablen namens strlen
geschossen, weil die Bibliotheksfunktion strlen
als Makro implementiert wurde. Zeitverschwendung Stunden durch die bizarro Fehlermeldungen, die verursacht.
Hinweis Sie können eine bestimmte Menge an Erfolg finden, indem Sie einfach die #define
verschieben, nachdem alle Header enthalten sind, aber die illegale Verwendung von typename
wird immer noch ein Auslösepunkt sein.
'typename' ist ein Schlüsselwort. Wenn es an Stellen erscheint, an denen es nicht erscheinen sollte, werden Fehler verursacht. Dies ist einer der Gründe, warum Makros vermieden werden sollten. – NathanOliver
Der [typenname] (http://en.cppreference.com/w/cpp/keyword/typename) ist ein reserviertes Schlüsselwort in C++. _typename1_ ist nicht. Bevorzugen Sie 'const' oder' constexpr' um 'define' zu definieren. – Ron
In 'C++' möchten Sie wahrscheinlich nicht #define verwenden. – drescherjm