C++ templates recursive aanroep

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • active2
  • Registratie: Juni 2001
  • Laatst online: 26-10-2024

active2

Google is your friend

Topicstarter
Ik heb een aardig probleempje voor de liefhebber...

De volgende code in de header files (dit is even een klein stukje om het probleem te visualiseren)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<class P, class D>
class Session {
  protected:
    D *_processor;
}

template<class P, class D>
class DataProcessor {
  protected:
    Session<P, D> *_session;
}

// Geen template
class Protocol {
}


Als ik nu de volgende code wil gaan gebruiken in een project dan krijg je iets in de trant van dit:
Session<Protocol, DataProcessor<Protocol, DataProcessor<...> >

Hoe kan ik er voor zorgen dat de compiler dit slikt, dit is een soort forward declaration wat ik nodig heb maar ik heb hier even niet het idee hoe ik dat kan oplossen.

De compiler die ik gebruik is g++ (GNU Compiler suite)

Als het gewone classes waren dan kon je forward declaration toepassen en was het voor elkaar.

Google, Het mirakel van de 21e eeuw!!!!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
kan je die niet gewoon forward declareren?

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
template<class P, class D>
class Session;

template<class P, class D>
class DataProcessor;

class Protocol;

template<class P, class D>
class Session {
  protected:
    D *_processor;
}

template<class P, class D>
class DataProcessor {
  protected:
    Session<P, D> *_session;
}

// Geen template
class Protocol {
}

Session<Protocol, DataProcessor<Protocol, DataProcessor<...> > mySession;

Of mag dat op de een of andere manier niet? Of snap ik je vraag niet helemaal?

[ Voor 3% gewijzigd door Woy op 29-05-2009 12:35 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • active2
  • Registratie: Juni 2001
  • Laatst online: 26-10-2024

active2

Google is your friend

Topicstarter
Ik denk dat je de vraag niet helemaal begreep.

Het gaat om de construction, dus wanneer je gebruik wil maken daar van:

code:
1
Session<Protocol, DataProcessor<Protocol, DataProcessor<...> > mySession;


Doordat je elke keer DataProcessor recursief mee geeft moet je zijn types ook steeds meegeven. En dan krijg je dus een oneindig aantal keer invullen:

code:
1
Session<Protocol, DataProcessor<Protocol, DataProcessor<Protocol, DataProcessor<.. mySession;


Dat is in feite het hele probleem.

Google, Het mirakel van de 21e eeuw!!!!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 02:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Kort antwoord: het kan niet.

Langer antwoord: Templates kunnen niet recursief. Het werkt met gewone classes wel omdat het type dan al bekend is. Wat je in feite wilt is dat de D van DataProcessor gelijk is aan het gehele type van DataProcessor zelf. Maar daarvoor moet je weer eerst definieren wat D is.

Er is wel een mogelijkheid, namelijk op de manier waarop je het met classes zou doen: DataProcessor weet namelijk van zichzelf wel wat voor type het is. Je kan met wat template trickery wel voor elkaar krijgen dat als je een speciale waarde voor D opgeeft, dat DataProcessor dan weet dat ie zichzelf moet gebruiken.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Het speciale type waarmee je aangeeft dat je de class zelf wil gebruiken in een template
struct Self
{
    // helper class om het juiste type te krijgen
    template<class T, class SelfType> struct GetType { typedef T type; };
};

// partial specialization voor het geval dat T == Self
template<class SelfType> struct Self::GetType<Self, SelfType> { typedef SelfType type; };

// Je DataProcessor
template<class P, class D> 
class DataProcessor { 
  typedef typename Self::GetType<D, DataProcessor>::type ActualD;
  // als D gelijk is aan Self, dan is ActualD gelijk aan DataProcessor<P, D>
  // zo niet, dan is ActualD gewoon D

  protected: 
    Session<P, ActualD> *_session; 
};

// Je session definitie
typedef Session<Protocol, DataProcessor<Protocol, Self> > MySession;

Zoiets. Niet getest :)

[ Voor 9% gewijzigd door .oisyn op 29-05-2009 13:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • active2
  • Registratie: Juni 2001
  • Laatst online: 26-10-2024

active2

Google is your friend

Topicstarter
Dat ga ik wel even testen. In elk geval alvast bedankt voor je antwoord!

Google, Het mirakel van de 21e eeuw!!!!


Acties:
  • 0 Henk 'm!

  • active2
  • Registratie: Juni 2001
  • Laatst online: 26-10-2024

active2

Google is your friend

Topicstarter
Gotcha! Working!

Google, Het mirakel van de 21e eeuw!!!!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ah nou snap ik je vraag idd. Het ligt er ook een beetje aan wat je met de templated type wilt doen, maar als alternatief op de oplossing van .oisyn zou je DataProcessor ook een non-templated parent (interface) kunnen geven. Dan heb je het probleem niet en krijg je bijvoobeeld
C++:
1
2
3
4
5
6
class AbstractDataProcessor
{
public:
    virtual void someNonTemplatedFuncs() = 0; 
}
Session<Protocol, AbstractDataProcessor> mySession;

Maar daar heb je natuurlijk alleen wat aan als je van het templated typed niet andere template paramters nodig hebt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

^^ with Woy

Interfaces zijn je vriend. Ik kan me niet inbeelden dat een van je interfaces een dependency zou hebben op een template parameter. Zelfs dat is op te lossen met interfaces door de interface te returnen waar anders een template parameter zou staan.

ASSUME makes an ASS out of U and ME

Pagina: 1