472,805 Members | 1,015 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,805 software developers and data experts.

Compilation problem with templates

Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue> {
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?

Thanks
Jerome
Apr 26 '07 #1
9 2602
Jerome Durand wrote:
Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue{
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?
It can be that the compiler is trying to resolve 'derived::valueType'
too soon (at the time when it encounters the 'typedef' in 'Base', the
'derived' is not completely defined yet. The behaviour of compilers
in this matter can differ somewhat, but the most concervative will
likely choke because 'derived' is incomplete by the time 'Base'
instantiation is attemtped. You might consider replacing the 'typedef'
dance with normal type processing:

template<typename valueTypestruct Base {
virtual valueType Value() = 0;
};

struct CharValue : Base<char{
char Value() { return 'a'; }
};

...

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 26 '07 #2
Victor Bazarov a écrit :
Jerome Durand wrote:
>Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue{
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?

It can be that the compiler is trying to resolve 'derived::valueType'
too soon (at the time when it encounters the 'typedef' in 'Base', the
'derived' is not completely defined yet. The behaviour of compilers
in this matter can differ somewhat, but the most concervative will
likely choke because 'derived' is incomplete by the time 'Base'
instantiation is attemtped. You might consider replacing the 'typedef'
dance with normal type processing:

template<typename valueTypestruct Base {
virtual valueType Value() = 0;
};

struct CharValue : Base<char{
char Value() { return 'a'; }
};

...

V
This is not really an option because I intend to have
several functions declared in base with different return
types which should depend on types defined in derived...

Jerome
Apr 26 '07 #3
Jerome Durand wrote:
Victor Bazarov a écrit :
>Jerome Durand wrote:
>>Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue{
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?

It can be that the compiler is trying to resolve 'derived::valueType'
too soon (at the time when it encounters the 'typedef' in 'Base', the
'derived' is not completely defined yet. The behaviour of compilers
in this matter can differ somewhat, but the most concervative will
likely choke because 'derived' is incomplete by the time 'Base'
instantiation is attemtped. You might consider replacing the
'typedef' dance with normal type processing:

template<typename valueTypestruct Base {
virtual valueType Value() = 0;
};

struct CharValue : Base<char{
char Value() { return 'a'; }
};

...

V

This is not really an option because I intend to have
several functions declared in base with different return
types which should depend on types defined in derived...
Then you're SOL since those types are members of the class which
is not going to be fully defined by the time Base is instantiated.
Catch 22.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Apr 26 '07 #4
Victor Bazarov a écrit :
Jerome Durand wrote:
>Victor Bazarov a écrit :
>>Jerome Durand wrote:
Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue{
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?
It can be that the compiler is trying to resolve 'derived::valueType'
too soon (at the time when it encounters the 'typedef' in 'Base', the
'derived' is not completely defined yet. The behaviour of compilers
in this matter can differ somewhat, but the most concervative will
likely choke because 'derived' is incomplete by the time 'Base'
instantiation is attemtped. You might consider replacing the
'typedef' dance with normal type processing:

template<typename valueTypestruct Base {
virtual valueType Value() = 0;
};

struct CharValue : Base<char{
char Value() { return 'a'; }
};

...

V
This is not really an option because I intend to have
several functions declared in base with different return
types which should depend on types defined in derived...

Then you're SOL since those types are members of the class which
is not going to be fully defined by the time Base is instantiated.
Catch 22.

V
Thank you Victor.

I did something a little differently to break the incomplete definition
dependency... Could have done it without an intermediate class, but I
felt it was better like this:
template <class aderived, class avaluetypestruct DerivedDescription {
typedef aderived derived;
typedef avaluetype valueType;

};
template <typename derivedDescriptionstruct Base{
typedef typename derivedDescription::valueType valueType;
virtual valueType Value() = 0;
};
struct CharValue: Base< DerivedDescription<CharValue, char{
typedef char valueType ;
valueType Value() {return 'a';}
};

struct IntValue: Base<DerivedDescription<IntValue, int>>{
typedef int valueType ;
valueType Value() {return 1234;}
};
Jerome

Apr 26 '07 #5
On Apr 26, 7:23 am, Jerome Durand <j.dur...@def2shoot.comwrote:
Hello,

I'm trying to write something along the following lines
but I cannot get this to compile.

template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue {
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'

Could someone tell me what is wrong with this?
You're effectively trying to use CharValue and IntValue before they're
defined. Why not simplify it like this:

template <typename Tstruct Base {
typedef T valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<char>{
valueType Value() {return 'a';}

};

struct IntValue: Base<int {
valueType Value() {return 1234;}
};

Cheers! --M

Apr 26 '07 #6
On Apr 26, 7:23 am, Jerome Durand <j.dur...@def2shoot.comwrote:
I'm trying to write something along the following lines
but I cannot get this to compile.

template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue {
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'

Could someone tell me what is wrong with this?
You're effectively trying to use CharValue and IntValue before they're
defined. Why not simplify it like this:

template <typename Tstruct Base {
typedef T valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<char>{
valueType Value() {return 'a';}

};

struct IntValue: Base<int {
valueType Value() {return 1234;}
};

Cheers! --M

Apr 26 '07 #7
mlimber a écrit :
On Apr 26, 7:23 am, Jerome Durand <j.dur...@def2shoot.comwrote:
>I'm trying to write something along the following lines
but I cannot get this to compile.

template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}

};

struct IntValue: Base<IntValue {
typedef int valueType ;
valueType Value() {return 1234;}
};

The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'

Could someone tell me what is wrong with this?

You're effectively trying to use CharValue and IntValue before they're
defined. Why not simplify it like this:

template <typename Tstruct Base {
typedef T valueType;
virtual valueType Value() = 0;
};

struct CharValue: Base<char>{
valueType Value() {return 'a';}

};

struct IntValue: Base<int {
valueType Value() {return 1234;}
};

Cheers! --M
because this is a trimmed down version of my problem,
where there's more than a single function and hence
more than a single return type required.

-J-
Apr 26 '07 #8
On Apr 26, 1:23 pm, Jerome Durand <j.dur...@def2shoot.comwrote:
I'm trying to write something along the following lines
but I cannot get this to compile.
template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};
struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}
};
struct IntValue: Base<IntValue {
typedef int valueType ;
valueType Value() {return 1234;}
};
The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
Could someone tell me what is wrong with this?
The error message could be clearer (mentionning e.g. incomplete
class), but if you think about how templates and class
definitions work, it should be obvious that this is impossible.
The use of the template as a base class triggers instantiation,
since a class must be complete to be used as a base, and
(§14.7.1/4) "A class template specialization is implicitly
instantiated if the class type is used in a context that
requires a completelydefined object type or if the completeness
of the class type might affect the semantics of the program."
(It's logical, really... what good would implicit instantiation
be otherwise.) In the template, derived::valueType is a
dependant name (obviously), so is resolved at the point of
instantiation. And (§14.6.4.1/3) "For a class template
specialization, [...] the point of instantiation for such a
specialization immediately precedes the namespace scope
declaration or definition that refers to the specialization."
Again, this is the only logical solution: you can't instantiate
(define) a class in the middle of your declaration, so it has to
be either before or after, and if it is after, you still don't
have a complete class to use as a base. Of course, if the point
of instantiation is before the definition of the class which
derives from the template, the contents of that class are not
accessible in the template.

Your basic problem is that you have created a cyclic
dependency. As written, Base can only be instantiated on a
complete class (since it uses contents of the class). And you
need an already instantiated Base in order to define the derived
class. The only solution is to break the cycle: make Base
independant of the derived class. In this case, for example,
you might pass valueType as a template argument, e.g.:

template< typename ValueType struct Base {
virtual ValueType value() = 0 ;
} ;

struct CharValue : Base< char { /* ... */ } ;
// etc.

If in your real code, this entails two or three parameters to
Base, so be it. If the number of parameters starts really
getting out of hand, you might also consider using traits. This
does make using Base somewhat more complicated, but it allows
considerably more flexibility.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 27 '07 #9
James Kanze a écrit :
On Apr 26, 1:23 pm, Jerome Durand <j.dur...@def2shoot.comwrote:
>I'm trying to write something along the following lines
but I cannot get this to compile.
> template <typename derivedstruct Base {
typedef typename derived::valueType valueType;
virtual valueType Value() = 0;
};
> struct CharValue: Base<CharValue>{
typedef char valueType ;
valueType Value() {return 'a';}
};
> struct IntValue: Base<IntValue {
typedef int valueType ;
valueType Value() {return 1234;}
};
>The compiler outputs (first error only):
Error 1: 'valueType' : is not a member of CharValue'
>Could someone tell me what is wrong with this?

The error message could be clearer (mentionning e.g. incomplete
class), but if you think about how templates and class
definitions work, it should be obvious that this is impossible.
The use of the template as a base class triggers instantiation,
since a class must be complete to be used as a base, and
(§14.7.1/4) "A class template specialization is implicitly
instantiated if the class type is used in a context that
requires a completelydefined object type or if the completeness
of the class type might affect the semantics of the program."
(It's logical, really... what good would implicit instantiation
be otherwise.) In the template, derived::valueType is a
dependant name (obviously), so is resolved at the point of
instantiation. And (§14.6.4.1/3) "For a class template
specialization, [...] the point of instantiation for such a
specialization immediately precedes the namespace scope
declaration or definition that refers to the specialization."
Again, this is the only logical solution: you can't instantiate
(define) a class in the middle of your declaration, so it has to
be either before or after, and if it is after, you still don't
have a complete class to use as a base. Of course, if the point
of instantiation is before the definition of the class which
derives from the template, the contents of that class are not
accessible in the template.

Your basic problem is that you have created a cyclic
dependency. As written, Base can only be instantiated on a
complete class (since it uses contents of the class). And you
need an already instantiated Base in order to define the derived
class. The only solution is to break the cycle: make Base
independant of the derived class. In this case, for example,
you might pass valueType as a template argument, e.g.:

template< typename ValueType struct Base {
virtual ValueType value() = 0 ;
} ;

struct CharValue : Base< char { /* ... */ } ;
// etc.

If in your real code, this entails two or three parameters to
Base, so be it. If the number of parameters starts really
getting out of hand, you might also consider using traits. This
does make using Base somewhat more complicated, but it allows
considerably more flexibility.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


all of this sounds very sensible. I don't have the standard, from
which I could have read where the point of instantiation for the
template is required to be, and it does make sense.

As you guessed, my real code needs more than a single parameter,
I finally found a solution on my own, which I find more tedious,
but works. I'll check how traits can be of use here...

I now have a solution to my problem and an explanation for it.
The latter is more precious than the former, it should later
help me to clear away from the same mistake in the first place.

Thank you James!
Jerome


Apr 27 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Ajay Daptardar | last post by:
Hi, I have the following problem. Consider this: // codec.h template <class T> class codec { public: codec(T val); private:
11
by: Alex Vinokur | last post by:
Hi, The code below has no problem with GNU g++ 3.3, but it has a problem with GNU g++ 3.4. What is reason for that? --------- foo.cpp : BEGIN --------- template <typename T> struct Boo
5
by: Mikael S. H. | last post by:
Header file compilation I'm coding a small irc bot, and I've noticed that compilation takes very long when I add certain header files (compared to compilation time without). I've tried to find...
4
by: Marcelo | last post by:
Hi everybody, This is my first time with the template class and I have an strange problem. I have spent all the afternoon trying to understand it, but I don't get the problem... I have three...
8
by: vitalyt | last post by:
Hi, I have cpp file which consist nested templates. Compilation time without optimization is 1-2 minutes, with -O2 turned on more then 5 hours. :( Could anybody help with that problem? AIX 5.2,...
7
by: =?iso-8859-2?q?Seweryn_Habdank-Wojew=F3dzki?= | last post by:
Hi There is an example of the code below (mostly written by P. Bindels). In that example is strongly highlighted that very important is the sequence of compiled code. In C++ could be assume...
6
by: pleexed | last post by:
hello, this is my first post in a newsgroup, i hope i do everything right :) first of all, i am sure there have been a lot of "are templates slow?" questions around, but i think what i would...
7
by: Christof Warlich | last post by:
Hi, can anyone tell why line 6 below gives the compilation error: error: expected primary-expression before '>' token Everything works fine if MemoryBlockSizes is replaced by a constant, e.g....
1
by: Alex Vinokur | last post by:
Hi, I have compilation problem on SUN CC compiler with template while using option -m64 (64-bit addressing model). No problem while using option -m32 (32-bit addressing model) $ CC -V CC:...
0
by: erikbower65 | last post by:
Using CodiumAI's pr-agent is simple and powerful. Follow these steps: 1. Install CodiumAI CLI: Ensure Node.js is installed, then run 'npm install -g codiumai' in the terminal. 2. Connect to...
0
linyimin
by: linyimin | last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
0
by: erikbower65 | last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA: 1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
2
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Sept 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM) The start time is equivalent to 19:00 (7PM) in Central...
0
by: Taofi | last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same This are my field names ID, Budgeted, Actual, Status and Differences ...
14
DJRhino1175
by: DJRhino1175 | last post by:
When I run this code I get an error, its Run-time error# 424 Object required...This is my first attempt at doing something like this. I test the entire code and it worked until I added this - If...
5
by: DJRhino | last post by:
Private Sub CboDrawingID_BeforeUpdate(Cancel As Integer) If = 310029923 Or 310030138 Or 310030152 Or 310030346 Or 310030348 Or _ 310030356 Or 310030359 Or 310030362 Or...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.