Toon posts:

[C++] Templates en 'Invalid return type specified' *

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo,

ik heb een probleem bij het compileren van een van m'n templated classes. Om een reden die ik niet begrijp wordt onderstaande code niet gecompileerd en krijg ik deze foutmelding:
qed.cpp: In instantiation of `B<Foo*>':
qed.cpp:40: instantiated from here
qed.cpp:29: error: conflicting return type specified for `const T B<T>::Test()
const [with T = Foo*]'
qed.cpp:14: error: overriding `virtual const Foo* A::Test() const'
De code waar het om draait:

code:
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
35
36
37
#include <iostream>

struct Foo {
    int val;
};



class A {
    public:
        A( void ) {
        }

        virtual const Foo* Test( void ) const {
            return NULL;
        }
};



template< class T >
class B : A {
    public:
        B( void ) {
        }

        const T Test( void ) const {
            return NULL;
        }
};



int main( void ) {
    A a;
    B< Foo* > b;
}


Zowel onder GCC als onder MSVC krijg ik vergelijkbare foutmeldingen, dus wellicht is het geen compiler bug o.i.d. maar een fundamentele C++ fout.

Overigens, als ik

code:
1
2
3
4
5
const T Test( void ) const {
.
.
.
B< Foo* > b;


vervang door:

code:
1
2
3
4
5
T Test( void ) const {
.
.
.
B< const Foo* > b;


compileert de code zonder problemen.

Iemand enig idee wat hier aan de hand is?

[ Voor 11% gewijzigd door Verwijderd op 28-04-2005 15:22 ]


  • gorgi_19
  • Registratie: Mei 2002
  • Nu online

gorgi_19

Kruimeltjes zijn weer op :9

C++ in de titel er bij :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 09:55

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 28 april 2005 @ 15:16:
dus wellicht is het geen compiler bug o.i.d. maar een fundamentele C++ fout.
Wat dacht je van een fundamentele fout in jouw code? A definieert een virtual functie Test met als return-type een const Foo *. Vervolgens heb je een B<T> die erft van A en doodleuk een const T maakt van dat returntype. Nou zijn covariant return-types toegestaan, maar een B<int> zal dus errors geven. Maar je gebruikt een B<Foo*>, dus dat zou goed moeten gaan volgens jou? Dus niet, jij maakt de Foo * zelf const, niet de Foo waar de pointer naar wijst. De pointer is dus const, niet Foo. Vergelijk:

C++:
1
2
Foo const * a;   // <-- dit is hetzelfde als const Foo * a, maar
Foo * const b;   // dit verduidelijkt de zaak wellicht
a mag je wijzigen, *a niet. b mag je niet wijzigen, *b wel.
A::Test heeft a als returntype, jij geeft met B<Foo*> echter een b.

[ Voor 16% gewijzigd door .oisyn op 28-04-2005 15:45 ]

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.


Verwijderd

Topicstarter
.oisyn schreef op donderdag 28 april 2005 @ 15:41:
[nohtml]Wat dacht je van een fundamentele fout in jouw code?
Misschien was ik niet helemaal duidelijk maar dat bedoelde ik dus.
.oisyn schreef op donderdag 28 april 2005 @ 15:41:

A definieert een virtual functie Test met als return-type een const Foo *. Vervolgens heb je een B<T> die erft van A en doodleuk een const T maakt van dat returntype. Nou zijn covariant return-types toegestaan, maar een B<int> zal dus errors geven. Maar je gebruikt een B<Foo*>, dus dat zou goed moeten gaan volgens jou? Dus niet, jij maakt de Foo * zelf const, niet de Foo waar de pointer naar wijst. De pointer is dus const, niet Foo. Vergelijk:

C++:
1
2
Foo const * a;   // <-- dit is hetzelfde als const Foo * a, maar
Foo * const b;   // dit verduidelijkt de zaak wellicht
a mag je wijzigen, *a niet. b mag je niet wijzigen, *b wel.
A::Test heeft a als returntype, jij geeft met B<Foo*> echter een b.[/nohtml]
Ok, dan is dat duidelijk. Ik ging er dus vanuit dat ik nog steeds te maken had met een pointer naar een const object. Bedankt.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Werkt ook niet op EDG (comeau).

Ik vermoed iets subtiels met two-phase compilatie. bij de eerste pass weet je T nog niet en kun je dus B<T>::Test nog niet compileren.

Oh ja, const pointers. Vieze dingen.

[ Voor 15% gewijzigd door MSalters op 28-04-2005 15:56 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Dan maar als goedmakertje de oplossing
C++:
1
2
3
4
template < typename T > struct makePtrConst {  typedef const T type; };
template < typename T > struct makePtrConst<T*> {  typedef const T* type; };
...
typename makePtrConst<T>::type Test( void ) const { return 0; }

[ Voor 16% gewijzigd door MSalters op 29-04-2005 12:46 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 09:55

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je vergeet een ::type ;)

Overigens zou ik het gewoon zo maken dat je geen Foo* maar een Foo hoeft op te geven, en dan gebruik je als return-type gewoon een const T *. Want waarom expliciet die pointer op moeten geven als de return-type toch wel covariant met een const Foo * moet zijn? Het is feitelijk alleen het Foo gedeelte van dat type dat kan veranderen (bijvoorbeeld een subclass van Foo), het moet verder wel een const T * zijn

[ Voor 90% gewijzigd door .oisyn op 28-04-2005 16:43 ]

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