template template und typename

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

template template und typename

Beitrag von kaiserludi »

Moin.

Kann mir wer erklären, wieso zwar das kompiliert (MCVC++ und clang)?

Code: Alles auswählen

template<typename EType>
class Foo
{
};

template<template<typename ENestedType> class EType>
class Foo<EType<class ENestedType> >
{
};
Das hier hingegen aber nicht (gleiche Compiler)?

Code: Alles auswählen

template<typename EType>
class Foo
{
};

template<template<typename ENestedType> typename EType>
class Foo<EType<typename ENestedType> >
{
};
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: template template und typename

Beitrag von dot »

Weil laut Standard dort das Schlüsselwort class stehen muss. Mutmaßlicher Hintergrund: Ein template template Parameter kann nur ein Klassentemplate sein...
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: template template und typename

Beitrag von kaiserludi »

Die Compiler brauchen aber auch ein "class" für ENestedType, auch dort funzt "typename" nicht, obwohl z.B. int natürlich auch bei Container<int> keine Klasse ist. Daher bezweifle ich, dass das mit der Klasse der Hintergrund ist, zumal typename ja im Standard als alternatives keyword für class im Zusammenhang von Templateparametern eingeführt wurde, um zu verdeutlichen, dass man primitive Typen als Templateparameter nutzen kann, und nicht, um eine Unterscheidung zwischen Templateparametern bei denen man auch primitive Typen unterstützt und welchen, bei denen nur Klassen akzeptiert werden, zu schaffen, denn man kann sie zwar so verwenden, aber das ist eine reine Stylevorliebe, ein template<class NotAPrimitve> class Foo verhindert ja nicht, dass man ein Foo<int> anlegt. Deswegen wundert es mich, dass man die beiden keywords bei template templates nicht in den Zusammenhängen equivalent zueinander einsetzen kann, in denen es ansonsten geht.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: template template und typename

Beitrag von dot »

kaiserludi hat geschrieben:Die Compiler brauchen aber auch ein "class" für ENestedType, auch dort funzt "typename" nicht, obwohl z.B. int natürlich auch bei Container<int> keine Klasse ist.
Bin mir nicht sicher was genau du damit meinst.
kaiserludi hat geschrieben:Daher bezweifle ich, dass das mit der Klasse der Hintergrund ist, zumal typename ja im Standard als alternatives keyword für class im Zusammenhang von Templateparametern eingeführt wurde, um zu verdeutlichen, dass man primitive Typen als Templateparameter nutzen kann, und nicht, um eine Unterscheidung zwischen Templateparametern bei denen man auch primitive Typen unterstützt und welchen, bei denen nur Klassen akzeptiert werden, zu schaffen, denn man kann sie zwar so verwenden, aber das ist eine reine Stylevorliebe, ein template<class NotAPrimitve> class Foo verhindert ja nicht, dass man ein Foo<int> anlegt.
Template type parameter sind der einzige Kontext in dem die Schlüsselwörter typename und class gleichwertig sind. Und hier handelt es sich um einen template template parameter. Ein template ist kein Typ...

Hier noch der entsprechende Auszug aus dem Standard:
ISO/IEC 14882:2011 hat geschrieben:The syntax for template-parameters is:
  • template-parameter:
    • type-parameter
    • parameter-declaration
  • type-parameter:
    • class ...opt identifieropt
    • class identifieropt = type-id
    • typename ...opt identifieropt
    • typename identifieropt = type-id
    • template < template-parameter-list > class ...opt identifieropt
    • template < template-parameter-list > class identifieropt = id-expression
Wie eindeutig zu sehen ist, ist bei einem template template parameter nur class erlaubt.
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: template template und typename

Beitrag von kaiserludi »

dot hat geschrieben:
kaiserludi hat geschrieben:Die Compiler brauchen aber auch ein "class" für ENestedType, auch dort funzt "typename" nicht, obwohl z.B. int natürlich auch bei Container<int> keine Klasse ist.
Bin mir nicht sicher was genau du damit meinst.
Es muss class Foo<EType<class ENestedType> > heißen, da class Foo<EType<typename ENestedType> > nicht kompiliert, aber das lässt sich nicht mit den bisherigen Erklärungen erklären: ENestedType aber ist kein template template Parameter und kann durchaus etwas anderes als ein Klassentemplate sein. Wieso muss da jetzt plötzlich ein class stehen?

Bei template<typename EType> class Foo<EType*>{}; ist schließlich auch zwar ein optionales typename erlaubt, so dass dann template<typename EType> class Foo<typename EType*>{}; lautet, aber ein class ist dort sogar ausdrücklich nicht erlaubt. Für nested Typen muss da aber nur ausdrücklich ein class stehen, was bei Etype als einzige der 3 Möglichkeiten (typename, class und gar nichts) nicht funktioniert.
dot hat geschrieben:
kaiserludi hat geschrieben:Daher bezweifle ich, dass das mit der Klasse der Hintergrund ist, zumal typename ja im Standard als alternatives keyword für class im Zusammenhang von Templateparametern eingeführt wurde, um zu verdeutlichen, dass man primitive Typen als Templateparameter nutzen kann, und nicht, um eine Unterscheidung zwischen Templateparametern bei denen man auch primitive Typen unterstützt und welchen, bei denen nur Klassen akzeptiert werden, zu schaffen, denn man kann sie zwar so verwenden, aber das ist eine reine Stylevorliebe, ein template<class NotAPrimitve> class Foo verhindert ja nicht, dass man ein Foo<int> anlegt.
Template type parameter sind der einzige Kontext in dem die Schlüsselwörter typename und class gleichwertig sind. Hier handelt es sich allerdings um einen template template parameter. Und ein template ist kein Typ.
Das erklärt zumindest, wieso das class in template<template<typename ENestedType> class EType> sein muss, wenn auch wie oben ausgeführt nicht das class in der Zeile darunter. Mir ist zwar bewusst, dass ein Klassentemplate nur eine Vorlage ist, aus der dann Klassen instantiert werden, und keine Klasse an sich, und damit streng genommen kein Typ, aber mir war nicht bewusst, dass das in diesem Zusammenhzang praktische Auswirkungen hat. Ich hätte gedacht, dass ein Klassentemplate dennoch wie ein Typ behandelt wird und nur zwischen type und nontype im Sinne von template<unsigned int nontype> Foo unterscheiden wird, da daraus ja nur Typen und keine nontype-arguments instantiert werden.

EDIT:
dot hat geschrieben: Hier noch der entsprechende Auszug aus dem Standard:
ISO/IEC 14882:2011 hat geschrieben:The syntax for template-parameters is:
  • template-parameter:
    • type-parameter
    • parameter-declaration
  • type-parameter:
    • class ...opt identifieropt
    • class identifieropt = type-id
    • typename ...opt identifieropt
    • typename identifieropt = type-id
    • template < template-parameter-list > class ...opt identifieropt
    • template < template-parameter-list > class identifieropt = id-expression
Wie eindeutig zu sehen ist, ist bei einem template template parameter nur class erlaubt.
Danke fürs raus suchen.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: template template und typename

Beitrag von dot »

kaiserludi hat geschrieben:Es muss class Foo<EType<class ENestedType> > heißen, da class Foo<EType<typename ENestedType> > nicht kompiliert [...]
Oh, darum gings dir!? Hab nicht genau genug geschaut, das ist mir bis gerade eben gar nicht aufgefallen. Das class dort ist bestenfalls unnötig und typename ist dort natürlich völliger Blödsinn. Was genau sollen class bzw. typename deiner Meinung nach dort tun? Bei genauerer Betrachung: Was genau soll das ganze Gebilde da eigentlich tun!?
kaiserludi hat geschrieben:Bei template<typename EType> class Foo<EType*>{}; ist schließlich auch zwar ein optionales typename erlaubt, so dass dann template<typename EType> class Foo<typename EType*>{}; lautet, aber ein class ist dort sogar ausdrücklich nicht erlaubt.
Das wundert mich jetzt, hast du das getestet? Was genau soll das typename dort tun?
kaiserludi hat geschrieben:Für nested Typen muss da aber nur ausdrücklich ein class stehen, was bei Etype als einzige der 3 Möglichkeiten (typename, class und gar nichts) nicht funktioniert.
Sry, ich hab immer noch keine Ahnung was genau das bedeuten soll. Kann es sein, dass du da typename und class gerade verwechselt hast? Denn dann würde das Sinn machen, denn der Zweck von typename ist ja genau, einen nested name in einem template als Typ zu kennzeichnen...
kaiserludi hat geschrieben:Mir ist zwar bewusst, dass ein Klassentemplate nur eine Vorlage ist, aus der dann Klassen instantiert werden, und keine Klasse an sich, und damit streng genommen kein Typ, aber mir war nicht bewusst, dass das in diesem Zusammenhzang praktische Auswirkungen hat. Ich hätte gedacht, dass ein Klassentemplate dennoch wie ein Typ behandelt wird und nur zwischen type und nontype im Sinne von template<unsigned int nontype> Foo unterscheiden wird, da daraus ja nur Typen und keine nontype-arguments instantiert werden.
Die Beziehung zwischen einem Typ und einem Template ist in etwa so wie die zwischen einem Objekt und einem Typ. Das sind einfach zwei völlig verschiedene Dinge. Template template parameter sind keine type parameter sind keine non-type parameter. Das sind drei völlig verschiedene Dinge. ;)
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: template template und typename

Beitrag von kaiserludi »

dot hat geschrieben:
kaiserludi hat geschrieben:Es muss class Foo<EType<class ENestedType> > heißen, da class Foo<EType<typename ENestedType> > nicht kompiliert [...]
Oh, darum gings dir!? Hab nicht genau genug geschaut, das ist mir bis gerade eben gar nicht aufgefallen. Das class dort ist unnötig und typename ist dort natürlich völliger Blödsinn. Was genau sollen class bzw. typename deiner Meinung nach dort tun? Bei genauerer Betrachung: Was genau soll das ganze Gebilde da eigentlich tun!?
Dass das class dort unnöig ist, hatte ich auch erwartet, aber ohne class mag es weder MSVC++ noch Clang kompilieren.
MSVC++ beschwert sich dann mit " C2065: 'ENestedType' : undeclared identifier", während Clang meint "Use of undeclared identifier 'ENestedType', Type name requires a specifier or qualifier, C++ requires a type specifier for all declarations"

Die Klassen sind natürlich im Einsatz nicht komplett leer, ich habe das zur Fehlerursacheneingrenzung vereinfacht gehabt. Ich will damit erreichen, dass je nachdem, ob EType ein Typ oder ein Template ist, verschiedene Versionen von Foo benutzt werden. Im Falle, dass es ein Template ist, soll rekursiv Foro<ENestedType> aufgerufen werden, solange, bis wir den Punkt erreichen, an dem EType kein template mehr sondern ein Type ist.

Wenn man z.B. sowas hat wie ContainerA<ContainerB<ContainerB<ContainerA<int**********>*****>***>**>******, dann will ich rekursiv über die template-Verschachtelung drüber gehen und für jede Templateparameterverschatelungsebene prüfen und speichern, wie viele * jeweils vorliegen und um was für einen Typ es sich jeweils handelt.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: template template und typename

Beitrag von dot »

kaiserludi hat geschrieben:Ich will damit erreichen, dass je nachdem, ob EType ein Typ oder ein Template ist, verschiedene Versionen von Foo benutzt werden.
Sowas in der Art dacht ich mir schon. Ich fürchte jedenfalls, dass das nicht so einfach machbar ist. Ich glaub aber, dass das, was du erreichen willst, sowieso auf anderem Wege besser gelöst werden kann...
kaiserludi hat geschrieben:Wenn man z.B. sowas hat wie ContainerA<ContainerB<ContainerB<ContainerA<int**********>*****>***>**>******, dann will ich rekursiv über die template-Verschachtelung drüber gehen und für jede Templateparameterverschatelungsebene prüfen und speichern, wie viele * jeweils vorliegen und um was für einen Typ es sich jeweils handelt.
Was genau du damit anstellen willst, will ich vermutlich gar nicht wissen...
Könnte man da nicht basierend auf ContainerType::value_type und SFINAE was basteln? Das erscheint mit zumindest sinnvoller. Selbst wenn du einen Weg über Template-Spezialisierungen findest, bist du dann wohl in Anzahl und Art der Parameter des Containertemplate eingeschränkt...
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: template template und typename

Beitrag von kaiserludi »

Ich habe eine Klasse Dictionary<keyType, valueType>, die im Grunde ein C++ Equivalent zu den Dictionay-Generics in C# und Java darstellt. Nun sind aber auch so lustige Sachen möglich wie Dictionary<String, <Dictionary<int, Dictionary<string, float**>**>>*, bei denen ausdrücklich eben auf der obersten Eben nicht irgend ein Dictionary als value akzeptiert wird, sondern nur ein Dictionary<int, Dictionary<string, float**>**>, welches dann wiederum als Values keine Dictionary<int, Dictionary<string, float**>, Dictionary<int, Dictionary<string, float**>* oder Dictionary<int, Dictionary<string, float**>*** akzeptiert, sondern nur Dictionary<int, Dictionary<string, float**>**. Die Compiletime Typechecks dafür funzen auch schon. Nun muss aber soetwas auch serialisiert werden können und dabei darf die Information, über die Elementtypen der verschiedenen Ebenen, die Pointerdimensionen und die Tiefe der Verschatelung nicht verloren gehen. Also muss ich diese ermitteln, damit ich sie in die serialisierte Form schreiben kann. Auch das Ermitteln klappt schon so weit, die benötigte Bytearraygröße für die Daten bekomme ich auch bereits zur Compilezeit und kann den Array also auch schon anlegen. Woran ich noch sitze, ist, die ermittelten Infos in den Array zu schreiben. Im Idealfall würde ich das gerne zur Compilezeit machen, da die Informationen zu diesem Zeitpunkt auch bereits ermittelt werden können. Ich will jetzt also zurKompilierzeit rekursiv durch die Verschachtelungstiefen des Templates und die vorgefundenen Infos in einen Array schreiben. Da ich zur Kompilierzeit mit spracheigenen Mitteln keinen Array befüllen kann, will ich dabei tricksen und eine verschachtelte POD struct ausspucken, die ich dann einfach in einen Array reinterpret-caste und mir dabei zunutze mache, dass die Daten so im Speicher liegen, dass ich mit Arrayzugriff auf den Speicher die für den Index korrekten Daten bekomme. Den Cast verstecke ich dann in einem operator[]()-Overload, so dass man von außerhalb der Implementierung die verschachtelte POD-struct wie einen Array benutzen kann.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: template template und typename

Beitrag von dot »

Nur mal so ein Gedanke, aber könnte man da nicht einfach eine freie serialize() Funktion verwenden und den Rest rekursiv von Overloading erledigen lassen!? Das wär zumindest mal mein erster Ansatz. Dein System klingt ja wahnsinnig kompliziert, was genau versprichtst du dir davon?
kaiserludi
Establishment
Beiträge: 467
Registriert: 18.04.2002, 15:31

Re: template template und typename

Beitrag von kaiserludi »

dot hat geschrieben:Nur mal so ein Gedanke, aber könnte man da nicht einfach eine freie serialize() Funktion verwenden und den Rest rekursiv von Overloading erledigen lassen!? Das wär zumindest mal mein erster Ansatz...
Die Funktion müsste ich dann zur Laufzeit ausführen. Das wäre mein Fallback, wenn ich keine mit realistischem Aufwand umsetzbare Variante finde, das zur Kompilierzeit zu machen.
"Mir ist auch klar, dass der Tag, an dem ZFX und Developia zusammengehen werden der selbe Tag sein wird, an dem DirectGL rauskommt."
DirectGL, endlich ist es da
:)

"According to the C++ standard, it's "undefined". That's a technical term that means, in theory, anything can happen: the program can crash, or keep running but generate garbage results, or send Bjarne Stroustrup an e-mail saying how ugly you are and how funny your mother dresses you." :shock:[/size]
Antworten