Seite 1 von 1

Template-Parameter kapseln

Verfasst: 19.06.2012, 22:40
von eXile
Und mal wieder etwas aus meinen Template-Abenteuern. Ich habe die kurze Frage, ob es irgendeine allgemein anwendbare Möglichkeit gibt, die Template-Parameterliste zu kapseln. Was ich damit meine, zeige ich an einem trivialen Beispiel:

Code: Alles auswählen

template <int i1, int i2>
struct adder
{
	enum
	{
		result = i1 + i2
	};
};

template <adder a, int i3>
struct fusedmultiplyadder1 // Geht natürlich nicht.
{
	enum
	{
		result = a::result * i3;
	};
};

template <int i1, int i2, int i3>
struct fusedmultiplyadder2 // Geht; Template-Liste wächst gegen infinity, and beyond!
{
	enum
	{
		result = adder<i1, i2>::result * i3
	};
};
Wie man sieht, geht bei fusedmultiplyadder2 die Parameterliste gegen unendlich, wenn man mal etwas Komplexeres machen will. Gibt es irgendeine gültige Variante von fusedmultiplyadder1?

Re: Template-Parameter kapseln

Verfasst: 19.06.2012, 22:59
von dot
Naja, ich vermute mal, du willst einfach variadic templates haben!?

Re: Template-Parameter kapseln

Verfasst: 19.06.2012, 22:59
von CodingCat
Du musst adder a nur durch typename a ersetzen. ;) Ja, das ist dann natürlich etwas überflexibel, für mehr bräuchtest du Concepts.

Re: Template-Parameter kapseln

Verfasst: 19.06.2012, 23:01
von dot
Jop, concepts + variadic templates...Ich fürchte im Moment müsste man da ansonsten wohl mit dem Präprozessor ran...

Re: Template-Parameter kapseln

Verfasst: 19.06.2012, 23:02
von CodingCat
Naja, ich sehe an der flexiblen Lösung nichts schlechtes, und einfach ist sie obendrein. Die Frage ist, warum es überhaupt der Einschränkung auf adder bedarf, vermutlich hängt noch irgendetwas komplexeres hinter diesem reduzierten Beispiel.

Re: Template-Parameter kapseln

Verfasst: 19.06.2012, 23:03
von dot
Ja, das stimmt natürlich...

Re: Template-Parameter kapseln

Verfasst: 20.06.2012, 00:28
von eXile
CodingCat hat geschrieben:Naja, ich sehe an der flexiblen Lösung nichts schlechtes, und einfach ist sie obendrein.
Ja, es ist dann halt duck typing.
CodingCat hat geschrieben:Die Frage ist, warum es überhaupt der Einschränkung auf adder bedarf, vermutlich hängt noch irgendetwas komplexeres hinter diesem reduzierten Beispiel.
Ja, das Beispiel ist zu stark reduziert; es soll hier im Anwendungsfall nur eine bestimmte Klasse an der Stelle verwendet werden dürfen. Wie gesagt: Das sind nur Hilfsklassen, um Schreibarbeit durch Verkürzung der Template-Parameter-Liste zu sparen, und diese Hilfsklassen können von außen gar nicht benutzt werden. Variadic Templates brauche ich hier auch nicht, da war das gegebene Beispiel einfach zu weit von meinem Anwendungsfall entfernt; sorry für das schlechte Beispiel.

Jetzt auch noch hier jeder Template-Klasse GUIDs zu geben, nur um Concepts mit SFINAE zu emulieren, geht mal gar nicht; aber so etwas habt ihr ja auch nicht vorgeschlagen. ;)

Ich habe es jetzt mal mit typename durchimplementiert, und gerade die angesprochene Flexibilität hat mir in den Hintern gebissen, weil ich doch auf ein paar Template-Parameter der verkapselnden Hilfsklassen zugreifen musste. Also wieder Kommando zurück, zurück zu den riesigen Listen, aber trotzdem danke für die Hilfe.

And now: To infinity, and beyond …
… und ich habe vorhin mit der Warnung C4503 die Name-Decorating-Schallmauer durchbrochen.

Re: Template-Parameter kapseln

Verfasst: 20.06.2012, 10:20
von CodingCat
eXile hat geschrieben:Ich habe es jetzt mal mit typename durchimplementiert, und gerade die angesprochene Flexibilität hat mir in den Hintern gebissen, weil ich doch auf ein paar Template-Parameter der verkapselnden Hilfsklassen zugreifen musste. Also wieder Kommando zurück, zurück zu den riesigen Listen, aber trotzdem danke für die Hilfe.
Hm, ich verstehe nicht, inwiefern du mit der Einschränkung besser auf Template-Parameter zugreifen könntest? Mir fallen eigentlich nur 2 Varianten ein:
  • Pattern Matching
    eXile hat geschrieben:
    CodingCat hat geschrieben:Naja, ich sehe an der flexiblen Lösung nichts schlechtes, und einfach ist sie obendrein.
    Ja, es ist dann halt duck typing.
    Fast, aber nicht im Rahmen von Pattern Matching. Hier könntest du sogar ganz einfach eine rekursive Dekomposition mit sehr spezifischen Einschränkungen durchführen.

Re: Template-Parameter kapseln

Verfasst: 20.06.2012, 16:02
von eXile
CodingCat hat geschrieben:Hm, ich verstehe nicht, inwiefern du mit der Einschränkung besser auf Template-Parameter zugreifen könntest? Mir fallen eigentlich nur 2 Varianten ein:
  1. Redefinition
  2. Pattern Matching
    Ja, das sind die Lösungen, die sich hier auch herauskristallisieren, und die Beschränkungen von C++ zeigen. Hätte ich eine Variante, welche:
    1. die Template-Template-Parameter eines Template-Parameters nimmt, und
    2. diese direkt der Template-Parameterliste als Template-Parameter hinzufügt,
    [/list][/list]
    würden sich ein paar Probleme hier verflüchtigen. Oder kurz: Template-Template-Parameter sollen so wie normale Template-Parameter behandelt werden; was aktuell offensichtlich unmöglich ist.
    CodingCat hat geschrieben:Fast, aber nicht im Rahmen von Pattern Matching. Hier könntest du sogar ganz einfach eine rekursive Dekomposition mit sehr spezifischen Einschränkungen durchführen.
    Das ist korrekt! Wobei bei mir auch noch hinzukommt, dass viele der dekomponierenden Einschränkungsklassen auch noch unterschiedlicher Natur sein können; siehe dafür diese Erweiterung deines Beispiels.

    Gibt es eine einfache Möglichkeit, das gültig zu machen? (Warum es nicht geht, ist mir klar: Es sind einfach unterschiedliche Typen. Ich brauche also „laxeres“ Pattern Matching.)

    Re: Template-Parameter kapseln

    Verfasst: 20.06.2012, 16:45
    von CodingCat
    eXile hat geschrieben:Hätte ich eine Variante, welche:
    1. die Template-Template-Parameter eines Template-Parameters nimmt, und
    2. diese direkt der Template-Parameterliste als Template-Parameter hinzufügt,
    würden sich ein paar Probleme hier verflüchtigen. Oder kurz: Template-Template-Parameter sollen so wie normale Template-Parameter behandelt werden; was aktuell offensichtlich unmöglich ist.
    Das musst du genauer erklären. Inwiefern sollen Template-Template-Parameter wie Template-Parameter behandelt werden?
    eXile hat geschrieben:Wobei bei mir auch noch hinzukommt, dass viele der dekomponierenden Einschränkungsklassen auch noch unterschiedlicher Natur sein können; siehe dafür diese Erweiterung deines Beispiels. Gibt es eine einfache Möglichkeit, das gültig zu machen? (Warum es nicht geht, ist mir klar: Es sind einfach unterschiedliche Typen. Ich brauche also „laxeres“ Pattern Matching.)
    Ja, einfach implizite Konvertierungen nutzen: http://ideone.com/K0k2b
    Mich würde ja echt interessieren, was du damit eigentlich baust. ;)

    Re: Template-Parameter kapseln

    Verfasst: 20.06.2012, 18:11
    von CodingCat
    Ich konnte es natürlich nicht lassen, noch etwas hübsches zu basteln.

    Re: Template-Parameter kapseln

    Verfasst: 20.06.2012, 18:42
    von CodingCat
    Für den allgemeinen Fall musste ich leider die Automatisierung etwas zurückfahren und noch mit virtual Inheritance nachbessern: http://ideone.com/q1FBz

    Re: Template-Parameter kapseln

    Verfasst: 21.06.2012, 15:30
    von eXile
    Das sieht hervorragend aus!

    Für alle, die auch da neben mir noch durchsteigen wollen, habe ich mal die Ableitungskette / -baum / -graphen aufgeschrieben. Für fma1:

    Code: Alles auswählen

    fusedmultiplyadder<adder1<2, 3>, 4>
     : public inherit_base_pattern<adder1<2, 3>, fusedmultiplyadder<adder<2, 3>, 4>>
        : public virtual fusedmultiplyadder<adder<2, 3>, 4>
    Damit matcht fusedmultiplyadder<adder1<2, 3>, 4> auf fusedmultiplyadder<adder<2, 3>, 4>. Und für fma4:

    Code: Alles auswählen

    fusedmultiplyadder1<adder2<2, 3>, 4>
     : public virtual fusedmultiplyadder<adder2<2, 3>, 4>
        : public inherit_base_pattern<adder2<2, 3>, fusedmultiplyadder<adder<2, 3>, 4>>
           : public virtual fusedmultiplyadder<adder<2, 3>, 4>,
       public inherit_base_pattern<adder2<2, 3>, fusedmultiplyadder1<adder<2, 3>, 4>>
        : public virtual fusedmultiplyadder1<adder<2, 3>, 4>
    Damit matcht fusedmultiplyadder1<adder2<2, 3>, 4> auf fusedmultiplyadder1<adder<2, 3>, 4> und auf fusedmultiplyadder<adder<2, 3>, 4>.
    CodingCat hat geschrieben:Mich würde ja echt interessieren, was du damit eigentlich baust. ;)
    Es hat nichts mit Mathematik zu tun, sondern es sind ein paar Hilfsklassen, die enum traits implementieren; als dass man über enums dann iterieren kann, und der Iterator verschiedene Policies besitzt, mit denen man entweder das enum von Anfang bis Ende einmal durchläuft; oder der Iterator am Ende umwrappt, und man den enum immer wieder in einer Schleife durchläuft. Hintergrund ist, dass ich keine Lust mehr hatte, immer auf so etwas wie if(myEnum == lastEnumElement) myEnum = firstEnumElement; else myEnum++; zu testen; nun muss ich nur myEnumIterator++; aufrufen. Wenn ich das auf obiges inherit_base_pattern umgestellt habe, dabei nicht auf die Nase geflogen bin, und das alles auch im g++ kompiliert (oh Gott mache ich dumme Fehler; aber Visual Studio sagt halt nichts) werfe ich das in die Public Domain, natürlich hier veröffentlicht. Und dann sagt ihr mir, warum das alles Scheiße war. :)

    Re: Template-Parameter kapseln

    Verfasst: 21.06.2012, 15:44
    von CodingCat
    eXile hat geschrieben:Hintergrund ist, dass ich keine Lust mehr hatte, immer auf so etwas wie if(myEnum == lastEnumElement) myEnum = firstEnumElement; else myEnum++; zu testen; nun muss ich nur myEnumIterator++; aufrufen. Wenn ich das auf obiges inherit_base_pattern umgestellt habe, dabei nicht auf die Nase geflogen bin, und das alles auch im g++ kompiliert (oh Gott mache ich dumme Fehler; aber Visual Studio sagt halt nichts) werfe ich das in die Public Domain, natürlich hier veröffentlicht. Und dann sagt ihr mir, warum das alles Scheiße war. :)
    Auweia, dann hoffe ich mal, dass dir virtual- und Mehrfachvererbung nicht sämtliche Optimierung ausschaltet. ;)