Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > templates and cyclic dependencies

Reply
Thread Tools

templates and cyclic dependencies

 
 
Leslaw Bieniasz
Guest
Posts: n/a
 
      09-20-2004

Cracow, 20.09.2004

Hi,

I am posting this again, because my previous message dated
18.09. disappeared from the list (someone has cancelled it ? why ??).

I have a problem with compiling the following construction involving
cross-calls of class template methods, with additional inheritance.
I want to have three class templates:

------------------------------------------
in file "Model.h":

#include "Data.h"

template<class T> class Model
{
....
void Read(Data<T> *data);
virtual int Get_Info(void);
};

template<class T>
void Model<T>::Read(Data<T> *data)
{
....
T something = data->Get(); // Note the Data method call
}

template<class T>
int Model<T>::Get_Info(void)
{
....
}

template class Model<float>;
template class Model<double>;

---------------------------------------
in file "Model1.h":

#include "Model.h"

template<class T> class Model1 : public Model<T>
{
....
virtual int Get_Info();
};

template<class T>
int Model1<T>::Get_Info(void)
{
....
}

template class Model1<float>;
template class Model1<double>;

----------------------------------------
in File "Data.h":

#include "Model.h"

template<class T> class Data
{
Data(Model<T> *model);
....
T Get(void);
};

template<class T>
Data<T>:ata(Model<T> *model)
{
....
int info = model->Get_Info(); // Note the virtual Model method call
}

template<class T>
T Data<T>::Get(void)
{
....
}

template class Data<float>;
template class Data<double>;

------------------------------------------
In the calling unit, file "Caller.h" I want to be able to do something
like this:

#include "Model.h"
#include "Model1.h"
#include "Data.h"

template<class T> class Caller
{
....
void call(void);
};

template<class T>
Caller<T>::call(void)
{
....
Model<T> *model = new Model1<T>();
....
Data<T> *data = new Data<T>(model);
....
model->Read(data);
....
}

template class Caller<float>;
template class Caller<double>;
---------------------------------------------------

I cannot figure out where to #include the various files and/or
where to provide forward class template declarations in order to avoid
compiler errors caused by nested inclusions of the header files, as
indicated. I have tried various combinations, such as not including
the headers, but using only forward declarations, or including the
headers after class declarations but before the method bodies. Nothing
helps.

I would appreciate any advice, also how to possibly redesign
the above code in order to have the same functionality and logic.
(I hope I have not introduced any spurious errors into the above
description, I am just writing this from memory, not from the
real code. In the real code certainly there are no typos or similar
errors. Please pay attention to the problem structure, not to details
of the statements). I use BCB 4.0, if this has any meaning.

Sincerely,

L.B.

*-------------------------------------------------------------------*
| Dr. Leslaw Bieniasz, |
| Institute of Physical Chemistry of the Polish Academy of Sciences,|
| Department of Electrochemical Oxidation of Gaseous Fuels, |
| ul. Zagrody 13, 30-318 Cracow, Poland. |
| tel./fax: +48 (12) 266-03-41 |
| E-mail: http://www.velocityreviews.com/forums/(E-Mail Removed) |
*-------------------------------------------------------------------*
| Interested in Computational Electrochemistry? |
| Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia |
*-------------------------------------------------------------------*
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      09-20-2004
Leslaw Bieniasz wrote:
> I am posting this again, because my previous message dated
> 18.09. disappeared from the list (someone has cancelled it ? why ??).


Nobody but you can cancel your message (usually). Check with your
ISP.

> I have a problem with compiling the following construction involving
> cross-calls of class template methods, with additional inheritance.
> I want to have three class templates:
>
> ------------------------------------------
> in file "Model.h":
>
> #include "Data.h"
>
> template<class T> class Model
> {
> ...
> void Read(Data<T> *data);


The compiler doesn't usually need to know what 'Data<T>' is here.
Since you're declaring the function with the pointer, you may just
forward-declare 'Data' at the beginning of 'Model.h'.

> virtual int Get_Info(void);
> };
>
> template<class T>
> void Model<T>::Read(Data<T> *data)
> {
> ...
> T something = data->Get(); // Note the Data method call


Here you'd usually need to know what 'Data' is since you're using
a member of it. The compiler needs to know the layout of the class
template.

> }
>
> template<class T>
> int Model<T>::Get_Info(void)
> {
> ...
> }
>
> template class Model<float>;
> template class Model<double>;


If you have explicit instantiations, you may hide all the implementation
in a C++ file. It's going to be even simpler from the inclusion point
of view.

>
> ---------------------------------------
> in file "Model1.h":
>
> #include "Model.h"
>
> template<class T> class Model1 : public Model<T>
> {
> ...
> virtual int Get_Info();
> };
>
> template<class T>
> int Model1<T>::Get_Info(void)
> {
> ...
> }
>
> template class Model1<float>;
> template class Model1<double>;
>
> ----------------------------------------
> in File "Data.h":
>
> #include "Model.h"
>
> template<class T> class Data
> {
> Data(Model<T> *model);


Same here. Since you declared a use of a pointer to Model<T>, you
just need to let the compiler know that Model<T> is a class template.
[Forward-]Declare the template at the beginning of the file instead
of including 'Model.h'.

> ...
> T Get(void);
> };
>
> template<class T>
> Data<T>:ata(Model<T> *model)
> {
> ...
> int info = model->Get_Info(); // Note the virtual Model method call
> }
>
> template<class T>
> T Data<T>::Get(void)
> {
> ...
> }
>
> template class Data<float>;
> template class Data<double>;
>
> ------------------------------------------
> In the calling unit, file "Caller.h" I want to be able to do something
> like this:
>
> #include "Model.h"
> #include "Model1.h"
> #include "Data.h"
>
> template<class T> class Caller
> {
> ...
> void call(void);
> };
>
> template<class T>
> Caller<T>::call(void)
> {
> ...
> Model<T> *model = new Model1<T>();
> ...
> Data<T> *data = new Data<T>(model);
> ...
> model->Read(data);
> ...
> }
>
> template class Caller<float>;
> template class Caller<double>;
> ---------------------------------------------------
>
> I cannot figure out where to #include the various files and/or
> where to provide forward class template declarations in order to avoid
> compiler errors caused by nested inclusions of the header files, as
> indicated. I have tried various combinations, such as not including
> the headers, but using only forward declarations, or including the
> headers after class declarations but before the method bodies. Nothing
> helps.


This is what should help: begin by forward-declaring everything and
then add the inclusions only when it is absolutely necessary. My
suspicion is that if you split your code into declarations and member
definitions, and then leave the declarations in the headers and move
the definitions in source files, you shouldn't have to include any
headers into headers, only into source files.

The compiler should know what to do because you provide the explicit
instantiations of your templates.

> [...]


V
 
Reply With Quote
 
 
 
 
Leslaw Bieniasz
Guest
Posts: n/a
 
      09-22-2004

Cracow, 22.09.2004

Hello,

On Mon, 20 Sep 2004, Victor Bazarov wrote:

> > I have a problem with compiling the following construction involving
> > cross-calls of class template methods, with additional inheritance.
> > I want to have three class templates:
> >
> > ------------------------------------------
> > in file "Model.h":
> >
> > #include "Data.h"
> >
> > template<class T> class Model
> > {
> > ...
> > void Read(Data<T> *data);

>
> The compiler doesn't usually need to know what 'Data<T>' is here.
> Since you're declaring the function with the pointer, you may just
> forward-declare 'Data' at the beginning of 'Model.h'.
>
> > virtual int Get_Info(void);
> > };
> >
> > template<class T>
> > void Model<T>::Read(Data<T> *data)
> > {
> > ...
> > T something = data->Get(); // Note the Data method call

>
> Here you'd usually need to know what 'Data' is since you're using
> a member of it. The compiler needs to know the layout of the class
> template.
>
> > }
> >
> > template<class T>
> > int Model<T>::Get_Info(void)
> > {
> > ...
> > }
> >
> > template class Model<float>;
> > template class Model<double>;

>
> If you have explicit instantiations, you may hide all the implementation
> in a C++ file. It's going to be even simpler from the inclusion point
> of view.
>
> >
> > ---------------------------------------
> > in file "Model1.h":
> >
> > #include "Model.h"
> >
> > template<class T> class Model1 : public Model<T>
> > {
> > ...
> > virtual int Get_Info();
> > };
> >
> > template<class T>
> > int Model1<T>::Get_Info(void)
> > {
> > ...
> > }
> >
> > template class Model1<float>;
> > template class Model1<double>;
> >
> > ----------------------------------------
> > in File "Data.h":
> >
> > #include "Model.h"
> >
> > template<class T> class Data
> > {
> > Data(Model<T> *model);

>
> Same here. Since you declared a use of a pointer to Model<T>, you
> just need to let the compiler know that Model<T> is a class template.
> [Forward-]Declare the template at the beginning of the file instead
> of including 'Model.h'.
>
> > ...
> > T Get(void);
> > };
> >
> > template<class T>
> > Data<T>:ata(Model<T> *model)
> > {
> > ...
> > int info = model->Get_Info(); // Note the virtual Model method call
> > }
> >
> > template<class T>
> > T Data<T>::Get(void)
> > {
> > ...
> > }
> >
> > template class Data<float>;
> > template class Data<double>;
> >
> > ------------------------------------------
> > In the calling unit, file "Caller.h" I want to be able to do something
> > like this:
> >
> > #include "Model.h"
> > #include "Model1.h"
> > #include "Data.h"
> >
> > template<class T> class Caller
> > {
> > ...
> > void call(void);
> > };
> >
> > template<class T>
> > Caller<T>::call(void)
> > {
> > ...
> > Model<T> *model = new Model1<T>();
> > ...
> > Data<T> *data = new Data<T>(model);
> > ...
> > model->Read(data);
> > ...
> > }
> >
> > template class Caller<float>;
> > template class Caller<double>;
> > ---------------------------------------------------
> >
> > I cannot figure out where to #include the various files and/or
> > where to provide forward class template declarations in order to avoid
> > compiler errors caused by nested inclusions of the header files, as
> > indicated. I have tried various combinations, such as not including
> > the headers, but using only forward declarations, or including the
> > headers after class declarations but before the method bodies. Nothing
> > helps.




> This is what should help: begin by forward-declaring everything and
> then add the inclusions only when it is absolutely necessary. My
> suspicion is that if you split your code into declarations and member
> definitions, and then leave the declarations in the headers and move
> the definitions in source files, you shouldn't have to include any
> headers into headers, only into source files.
>
> The compiler should know what to do because you provide the explicit
> instantiations of your templates.


This will not work, because according to the current C++ standard all
template stuff (except perhaps for the explicit instantiations) MUST go
into headers, otherwise the code cannot be compiled. This is the
problem. The errors are detected while parsing the definitions of the
class template methods, not while parsing the class template declaration (in the
latter case forward declarations are indeed sufficient), because in the
definitions not only pointers or references to other classes occur,
but method calls.

L.B.


*-------------------------------------------------------------------*
| Dr. Leslaw Bieniasz, |
| Institute of Physical Chemistry of the Polish Academy of Sciences,|
| Department of Electrochemical Oxidation of Gaseous Fuels, |
| ul. Zagrody 13, 30-318 Cracow, Poland. |
| tel./fax: +48 (12) 266-03-41 |
| E-mail: (E-Mail Removed) |
*-------------------------------------------------------------------*
| Interested in Computational Electrochemistry? |
| Visit my web site: http://www.cyf-kr.edu.pl/~nbbienia |
*-------------------------------------------------------------------*
 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      09-22-2004
Leslaw Bieniasz wrote:
> [...]
> This will not work, because according to the current C++ standard all
> template stuff (except perhaps for the explicit instantiations) MUST go
> into headers, otherwise the code cannot be compiled.


I don't want this to go into "must -- must not" type of argument, but
I don't have time to provide you with examples either. I will just say
that if you define the template class (with all members _declared_) and
use _explicit_instantiations_ in the same header, you _don't_ need all
the member definitions in the same header. If you know what I am talking
about, you can try it yourself. Sapienti sat.

Otherwise, use a compiler that supports 'export' keyword. IOW, what you
said about "according to the current C++ standard" only shows your poor
knowledge of the standard. No offense intended.

> [...]


V
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
intrusive smart pointers and cyclic type dependencies Marcel Müller C++ 0 08-08-2009 09:01 PM
Smart pointer and cyclic dependencies Marcel Müller C++ 1 03-22-2008 10:39 AM
Forward Declaration produces an error (no cyclic dependencies tho) elmar_macek@gmx.de C++ 2 09-26-2007 12:50 PM
Cyclic dependencies and namespaces. Craig Sanders C++ 1 09-05-2007 04:51 PM
Cyclic dependencies xiaohuamao C++ 1 08-09-2006 09:47 AM



Advertisments