[C++, GCC] templatised base classes

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Darkvater
  • Registratie: Januari 2001
  • Laatst online: 26-08-2024

Darkvater

oh really?

Topicstarter
Stel ik heb de volgende klasse:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <class T> class BASE {
public:
  BASE(int N) {
    _val = new T[N];
  }
private:
  T* _val;
};

class DERIVED: public BASE<int> {
public:
  DERIVED(): BASE(5) {}
};

int main() {
  DERIVED a;
  return 0;
}


Als ik dit compile in MSVC (2008) dan is het helemaal perfect en goed. Echter met GCC (4.4.1) krijg ik de volgende foutmelding:
code:
1
2
3
4
5
test.cpp: In constructor DERIVED::DERIVED():
test.cpp:12: error: class DERIVED does not have any field named BASE
test.cpp:12: error: no matching function call to BASE<int>::BASE()
test.cpp:3: note: candidates are: BASE<T>::BASE(int) [with T = int]
test.cpp:1: note:                          BASE<int>BASE(const BASE<int>&)


WTF? Moet ik nou echt DERIVED(): BASE<int>(5) {} doen en overal de template specialisation van BASE doorgeven? Kan dit niet op een andere manier? Voor mijn eigen classes is dit niet zo'n heel groot probleem maar ik gebruik ook BOOST::spirit en daar is het echt een ramp om alles uit te schrijven.


Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge


Acties:
  • 0 Henk 'm!

  • MisterData
  • Registratie: September 2001
  • Laatst online: 29-08 20:29
Helaas, zo werkt het (voor zover ik weet) inderdaad. Wat je kunt doen is een default type opgeven:

C++:
1
template <class T=int> class BASE


Als je die specialisatie het meest gebruikt. Je kunt ook DERIVED templated maken:

C++:
1
template <class X> class DERIVED: pubic BASE<X>


Als de dingen tussen de template<> te lang zijn, kun je dat misschien typedeffen naar iets korters, ofzo...

Acties:
  • 0 Henk 'm!

  • Darkvater
  • Registratie: Januari 2001
  • Laatst online: 26-08-2024

Darkvater

oh really?

Topicstarter
Ik heb nog even rondgekeken bij je typedef idee, en het volgende werkt:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template <class T> class BASE {
public:
  typedef BASE<T> base_type;

  BASE(int N) {
    _val = new T[N];
  }
private:
  T* _val;
};

class DERIVED: public BASE<int> { 
public: 
  DERIVED(): DERIVED::base_type(5) {} 
};


Een typedef maken dus in de base classe met de template types erin en dan die gebruiken. Verdient geen schoonheidsprijs maar het compilet tenminste :s


Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Darkvater schreef op maandag 04 januari 2010 @ 10:07:
WTF? Moet ik nou echt DERIVED(): BASE<int>(5) {} doen en overal de template specialisation van BASE doorgeven?
Natuurlijk moet dat. Hoe weet de compiler anders welke base class je aan het instantieren bent met die parameters? In jouw voorbeeld is het natuurlijk vrij duidelijk, maar hier niet:
C++:
1
2
3
4
5
6
7
class DERIVED : public BASE<int>, public BASE<float>
{
public:
    DERIVED() : BASE(5) // welke bedoel je nu?
    {
    }
};

BASE is binnen de (privé) context van BASE<T> gewoon een alias voor BASE<T>. Maar daarbuiten bestaat hij niet meer, en is BASE gewoom een template-id.

Jouw oplossing geeft wat dat betreft in deze case ook een compile error, want nu is DERIVED::base_type ambigu. Je zou de typedefs ook gewoon in DERIVED zelf kunnen zetten.

[ Voor 10% gewijzigd door .oisyn op 04-01-2010 15:47 ]

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!

  • Xiphalon
  • Registratie: Juni 2001
  • Laatst online: 16-09 16:54
Flauw/interessemodus: 5 is toch een int constante (5.0 of 5Fzou de float zijn) dus de compiler kan het e.e.a hier toch inferren?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Nee, want elke BASE<T> ctor heeft een int als parameter. Dus ook BASE<float>. Maar goed, afgezien van dat, dat inferren doet ie sowieso niet.

[ Voor 44% gewijzigd door .oisyn op 04-01-2010 16:15 ]

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!

  • Darkvater
  • Registratie: Januari 2001
  • Laatst online: 26-08-2024

Darkvater

oh really?

Topicstarter
.oisyn schreef op maandag 04 januari 2010 @ 15:41:
[...]

Jouw oplossing geeft wat dat betreft in deze case ook een compile error, want nu is DERIVED::base_type ambigu. Je zou de typedefs ook gewoon in DERIVED zelf kunnen zetten.
Kennelijk is het wel weer compiler-afhankelijk aangezien GCC dit wel accepteert, en MSVC deze base_type niet eens nodig heeft. Ik snap je redenering wel.


Windows Vista? *NEVER* Het waarom - Opera forever!!!
I've seen chickens that were more menacing. Chickens in a coma. On ice. In my fridge


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het is in zoverre compiler afhankelijk dat MSVC++ zich op dit punt niet aan de standaard houdt. Op die manier is natuurlijk alles compiler-afhankelijk :)

[ Voor 69% gewijzigd door .oisyn op 04-01-2010 16:54 ]

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!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

base_type is alleen non-ambigu als je maar van 1 base derived. als dat in alle gevallen zo is, dan kan je inderdaad base_type gebruiken.

typedefs in derived zetten werkt natuurlijk wel, maar heeft als (klein) nadeel dat je je niet kan deriven van je typedeffed naam, waardoor je alsnog 2x je type moet uitschrijven (met mogelijke bugs als ze niet meer overeenkomen later)
C++:
1
2
3
4
class derived : base_specialization //compile error, base_specialization nog niet defined
{
  typedef base<int> base_specialization;
}

-niks-


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 01:04

.oisyn

Moderator Devschuur®

Demotivational Speaker

MLM schreef op maandag 04 januari 2010 @ 18:58:
typedefs in derived zetten werkt natuurlijk wel, maar heeft als (klein) nadeel dat je je niet kan deriven van je typedeffed naam, waardoor je alsnog 2x je type moet uitschrijven (met mogelijke bugs als ze niet meer overeenkomen later)
Echter werkt de typedef in je base ook niet meer als je derived zelf een ook template class is. De base_type is dan een dependent type, en zul je base sowieso moeten uitschrijven waardoor een typedef in de derived zelf vaak alsnog gewenst is.

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.

Pagina: 1