De afgelopen dagen ben ik bezig met het ontwikkelen van een module die de resultaten van een simulatie code die we hier gebruiken moet wegschrijven. De code is in C++.
Mijn idee was om een base class 'OutputWriter' te maken, waarvan verschillende implementaties (ASCIIWriter, BinaryWriter, MysqlWriter etc, etc) overerven.
Vervolgens moet elke implementatie methoden implementeren die verschillende (data)typen kunnen wegschrijven (double, int, verschillende objecten).
Nu was mijn eerste idee iets als (note: ik heb alle code zoveel mogelijk uitgekleed...):
Maar dat werkt niet, virtual methods kunnen niet ge-template worden, wat natuurlijk (enigszins) logisch is.
Nu kwam ik na wat omzwervingen (note: mijn C++ kennis, en vooral mijn design-pattern kennis is nou niet bepaald geweldig) op het Curiously recurring template pattern.
Ofwel, een vorm van static polymorphisme, die mij het volgende laat doen:
Dus de implementaties SomeWriter en AnotherWriter geven zichzelf als template parameter mee aan de base class, waardoor deze via een static_cast de methode 'write()' van de Derived class kan aanroepen...
Uiteraard zijn in mijn uiteindelijke code de write() methoden van de verschillende implementaties compleet anders
Nu, dit komt erg dicht in de buurt van wat ik wil, maar....
Hiermee kan ik nog niet at runtime kiezen welke implementatie ik gebruik zoals ik met dynamic polymorphisme zou kunnen doen. Uiteindelijk wil ik natuurlijk iets doen als:
Wat uiteraard niet compiled omdat de declaratie van een 'OutputWriter* w' pointer een template argument mist...
Nu, ik heb vaag het idee dat wat ik wil gewoon tegen het strong-type principe van C++ indruist...
Maar met het plaatsen van dit topic hoop ik enerzijds duidelijk te krijgen of wat ik wil inderdaad gewoon niet kan, of anderzijds een oplossing of alternatief te vinden...
Mijn idee was om een base class 'OutputWriter' te maken, waarvan verschillende implementaties (ASCIIWriter, BinaryWriter, MysqlWriter etc, etc) overerven.
Vervolgens moet elke implementatie methoden implementeren die verschillende (data)typen kunnen wegschrijven (double, int, verschillende objecten).
Nu was mijn eerste idee iets als (note: ik heb alle code zoveel mogelijk uitgekleed...):
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
| class Writer{ public: template <class T> virtual void write(string name, T value)=0; }; class AsciiWriter{ public: template <class T> void write(string name, T value){ cout<<value<<endl; } } |
Maar dat werkt niet, virtual methods kunnen niet ge-template worden, wat natuurlijk (enigszins) logisch is.
Nu kwam ik na wat omzwervingen (note: mijn C++ kennis, en vooral mijn design-pattern kennis is nou niet bepaald geweldig) op het Curiously recurring template pattern.
Ofwel, een vorm van static polymorphisme, die mij het volgende laat doen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| #include <iostream> using namespace std; template <class Derived> class Writer{ public: template <class T> void write(T value) { static_cast<Derived*>(this)->write(value); } }; class SomeWriter : public Writer<SomeWriter > { public: template <class T> void write(T value){ cout<<"SomeWriter: "<<value<<endl; } }; class AnotherWriter : public Writer<AnotherWriter > { public: template <class T> void write(T value){ cout<<"AnotherWriter: "<<value<<endl; } }; int main(){ SomeWriter s; s.write("tekst"); AnotherWriter a; a.write(1.3); } |
Dus de implementaties SomeWriter en AnotherWriter geven zichzelf als template parameter mee aan de base class, waardoor deze via een static_cast de methode 'write()' van de Derived class kan aanroepen...
Uiteraard zijn in mijn uiteindelijke code de write() methoden van de verschillende implementaties compleet anders
Nu, dit komt erg dicht in de buurt van wat ik wil, maar....
Hiermee kan ik nog niet at runtime kiezen welke implementatie ik gebruik zoals ik met dynamic polymorphisme zou kunnen doen. Uiteindelijk wil ik natuurlijk iets doen als:
C++:
1
2
3
4
5
6
| OutputWriter* w; if(...){ w = SomeWriter(); }else{ w = AnotherWriter(); } |
Wat uiteraard niet compiled omdat de declaratie van een 'OutputWriter* w' pointer een template argument mist...
Nu, ik heb vaag het idee dat wat ik wil gewoon tegen het strong-type principe van C++ indruist...
Maar met het plaatsen van dit topic hoop ik enerzijds duidelijk te krijgen of wat ik wil inderdaad gewoon niet kan, of anderzijds een oplossing of alternatief te vinden...