Re: Templates and forward declarations
On Sep 25, 12:49 pm, Rune Allnor <all...@tele.ntnu.no> wrote:
Hi all.
I have these classes, implemented as templates in header files.
Right now I have one file per class, where both the declarations
and implementations of one class are located in each file.
I would like to apply the visitor pattern to some of these classes.
One of the technicalities behind the visitor pattern is that one
needs forward declarations of classes, since there are two
class hierarchies which refer to each other.
In C++ one can refer to a yet undeclared class in one class'
*declaration*, but one can't refer to undeclared classes in the
*implementation*. Since the declaration and implementation
of my classes reside in the same file, my nice system breaks
down.
Or I need to set up a very entangled network of declarations
and implementations, which at the end *might* compile *if*
all the dependencies are carefully orchestrated. Which in turn
means that all classes need to know about all the other classes,
which ultimately destroys the nice modular class hierarchy I
have right now. Or I can lump lots of classes together in one
header file, which not quite as bad, but hardly modular.
One tempting conclusion from all this is that templates don't
go well with forward declarations *and* a modular design.
This seems a bit too 'over the top' to be accepted just like
that, so am I overlooking something?
Try the following layout:
<file "A.h">
#if !defined(A_H_INCLUDE_GUARD)
#define A_H_INCLUDE_GUARD
template<class T> struct B;
template<class T>
struct A
{
void f(B& b);
}
#include "A.ipp"
#endif // !defined(A_H_INCLUDE_GUARD)
</file>
<file "A.ipp">
include "B.h"
template<class T>
void A<T>::f(B& b)
{
// do something with b here
}
</file>
<file "B.h">
#if !defined(B_H_INCLUDE_GUARD)
#define B_H_INCLUDE_GUARD
template<class T> struct A;
template<class T>
struct B
{
void f(A& a);
}
#include "B.ipp"
#endif // !defined(B_H_INCLUDE_GUARD)
</file>
<file "B.ipp">
include "A.h"
template<class T>
void B<T>::f(A& a)
{
// do something with a here
}
</file>
You set up your files the same way as for non-template classes, with
the following difference: The implementation file is not compiled as a
separate translation unit, but is instead #included at the end of the
header file (within the include guard). The suffix .ipp is commonly
used to distinguish the file from .cpp (compiled as a separate
translation unit) and .h/.hpp (an interface file included wherever
needed).
Yechezkel Mett
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]