473,480 Members | 1,856 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

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 2648
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
1546
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
416
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
5839
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
2717
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
1762
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
1934
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
1437
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
184
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
2641
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
6904
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7032
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7076
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
6873
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5321
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4767
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
2990
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
1294
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
558
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.