Lokale Klassen und templates: Warum kann man nicht beides haben?
-
Hallo,
man kann ja in Funktionen lokale Klassen anlegen:
int main(){ class foo { }; foo bar; }Warum darf man lokal keine Klassentemplates verwenden? Folgendes geht nicht:
int main(){ template <class T> class foo // Compilerfehler: Expected primary-expression before 'template' { }; foo<int> bar; }Dazu 2 Fragen:
Warum geht das nicht? Mir ist der Grund nicht klar, warum der Compiler solch einen Ausdruck nicht übersetzen kann. Schreibe ich die Templatedefinition in den globalen Dateibereich kann es übersetzt werden, warum funktioniert das nicht auch rein lokal wie bei Klassendefinitionen?Weiß jemand einen Trick, das dennoch hinzubekommen?
-
Warum geht das nicht?
Ist halt so. Ist laut Standard nicht erlaubt.
Mir ist der Grund nicht klar, warum der Compiler solch einen Ausdruck nicht übersetzen kann.
Könnte er, darf er aber nicht.
Schreibe ich die Templatedefinition in den globalen Dateibereich kann es übersetzt werden, warum funktioniert das nicht auch rein lokal wie bei Klassendefinitionen?
Du wiederholst dich. Antwort bleibt die selbe: weil der Standard es nicht erlaubt.
Weiß jemand einen Trick, das dennoch hinzubekommen?
Verwende einen unnamed namespace.
-
hustbaer schrieb:
Warum geht das nicht?
Ist halt so. Ist laut Standard nicht erlaubt....
Trotzdem wäre es schön, zu erfahren, warum der Standardisierungsausschuss sich die Mühe machte, das da reinzuschreben...
Es ist doch eher die Regel, dass die Standardvorgaben nicht zufällig entstanden sind (TROTZ Darwinjahr
)Gruß,
Simon2.
-
Simon2 schrieb:
warum der Standardisierungsausschuss sich die Mühe machte, das da reinzuschreben...
Es ist doch eher andersrum. Im Standard ist explizit erlaubt, dass es lokale Klassen geben darf. Von lokalen Klassentemplates samt eventueller Instantiierung ist nirgendwo die Rede, deshalb wirds auch nicht implementiert.
-
Werden lokale Klassen von euch eigentlich benutzt? Wenn ja, wozu? Vielleicht Funktoren?
Ich habe selber noch nie eine Klasse lokal definiert.
-
Bei mir nicht. Funktoren, also jetzt Klassen mit überladenem ()-Operator stehen bei mir (wenn's auch um STL geht) in einem eigenen Namensraum. Es gibt keinen Grund, eine Klasse in der main zu definieren, eine in einer Funktion zeigt auch noch verdammt schlechten Geschmack.
-
Ad aCTa schrieb:
Es gibt keinen Grund, eine Klasse in der main zu definieren, eine in einer Funktion zeigt auch noch verdammt schlechten Geschmack.
ROFL
Dann habe ich wohl verdammt schlechten Geschmack. Es ist bisher zwar noch nicht oft aufgetaucht, aber ich habe einmal eine Klasse benötigt, um genau zu sein ein struct als Visitor für ein Boost.Variant. Ich habe es nirgends ausser in dieser Funktion benötigt. Die Funktion hatte daher am Anfang eine Strukturdefinition und danach einen Funktionensaufruf und das Resultat wurde zurückgegeben.Ich empfand dies als übersichtlicher. So war alles beisammen, was auch gleich zusammengehört. Überdimensionierter Lambda-Ausdruck

Grüssli
-
pumuckl schrieb:
Simon2 schrieb:
warum der Standardisierungsausschuss sich die Mühe machte, das da reinzuschreben...
Es ist doch eher andersrum. Im Standard ist explizit erlaubt, dass es lokale Klassen geben darf. Von lokalen Klassentemplates samt eventueller Instantiierung ist nirgendwo die Rede, deshalb wirds auch nicht implementiert.
Ach so!
Dann reicht es natürlich schon aus, wenn es niemand vermisst hat...Gruß,
Simon2.
-
Ich bin mir fast sicher, dass das mit dem "zusammenfassen" von Template-Instanzen zu tun hat.
External-Linkage bedeutet nunmal dass ein "Ding" (Funktion, statische/globale Variable) einen eindeutigen "Namen" (oder "ID") haben muss. Anhand dieses Namens können Template-Instanzen beim Linken schön zusammengefasst werden - indem man nämlich einfach eine x-beliebige Instanz pro Namen auswählt, und alle anderen wegwirft.
Für "normale" Funktionen ist das verboten, für Templates (ausgenommen vollständig spezialisierte Funktionstemplates!) und "inline" Funktionen ist es aber erlaubt.Templates mit Internal Linkage zu erlauben (und lokale Klassen haben Internal Linkage!) würde die Sache verkomplizieren.
Dasselbe gilt für Template-Parameter, weswegen dashier nicht geht:
void foo() { class bar {}; std::vector<bar> vec; // Fehler: Template-Parameter müssen External Linkage haben! }p.S.: weiss jemand, ob der Standard es erlaubt, lokale Klasse in inline-Funktionen zu verwenden? MSVC spuckt da nämlich Zahnräder (wenn die inline Funktion in >= zwei TUs vorkommt - sonst nicht).
Muss ich gleich nachgucken wenn ich zuhause bin...
-
Dravere schrieb:
Ad aCTa schrieb:
Es gibt keinen Grund, eine Klasse in der main zu definieren, eine in einer Funktion zeigt auch noch verdammt schlechten Geschmack.
ROFL
Dann habe ich wohl verdammt schlechten Geschmack. Es ist bisher zwar noch nicht oft aufgetaucht, aber ich habe einmal eine Klasse benötigt, um genau zu sein ein struct als Visitor für ein Boost.Variant. Ich habe es nirgends ausser in dieser Funktion benötigt. Die Funktion hatte daher am Anfang eine Strukturdefinition und danach einen Funktionensaufruf und das Resultat wurde zurückgegeben.Ich empfand dies als übersichtlicher. So war alles beisammen, was auch gleich zusammengehört. Überdimensionierter Lambda-Ausdruck

Grüssli
Naja, ich dachte da mehr an Classes. Structs, enums und unions sind natürlich mehr Mittel zum Zweck, unter einer "Klasse" verstehe ich etwas größeres als ein Struct, die sind für mich mehr Transportmittel, so wie z.B. std::pair.
-
Ad aCTa schrieb:
Naja, ich dachte da mehr an Classes. Structs, enums und unions sind natürlich mehr Mittel zum Zweck, unter einer "Klasse" verstehe ich etwas größeres als ein Struct, die sind für mich mehr Transportmittel, so wie z.B. std::pair.
Deine Definition des Unterschieds zwischen class und struct ist ein ziemlich persönlicher. Technisch sind struct und class das selbe - von dem kleinen Unterschied der default Sichtbarkeit mal abgesehn.
Natürlich wird niemand eine lokale Monsterklasse definieren. Denn das würde bedeuten dass man deren ganze Funktionalität in der Funktion bräuchte - was wiederum eine Monsterfunktion voraussetzt.
Da Funktionen normalerweise kurz gehalten werden, gilt das selber für lokale Klassen. Der häufigste Fall für lokale Klassen dürften Funktoren sein, die für Algorithmen benutzt werden.
Ich persönlich benutze lokale Klassen genau zu dem Zweck.