[Insight-users] Forward references to ITK classes

Paul Yushkevich pauly@cognitica.com
Sun, 30 Mar 2003 15:38:50 -0500


I have a [rather long] question about using forward references to ITK 
classes.  My guess is that I am not the first person to face this issue, 
but I have not seen any questions regarding this on the mailing list.

Suppose I have the following situation:

A templated class Wrapper<TPixel> encapsulates a generic image 
processing task and contains pointers to multiple images and filters. 
This class is used throughout a large application.  The class is 
declared in the header file "Wrapper.h", and this file is included by 
many other files in the application.

In order to reduce compilation time, I would like to use forward 
references to ITK classes needed to declare the class Wrapper in the 
header "Wrapper.h".  The following declaration is possible:

// Forward references, no need to include ITK headers here
namespace itk {
    template <int i, class T> class Image;
    template <class TInput, class TOutput> class SomeFilter;
};

template <class TPixel> class Wrapper {
    typedef itk::Image<3,TPixel> ImageType; // and so on
private:
    ImageType *m_FirstImage,*m_SecondImage; // and so on
};

This works fine but... this declaration does not use SmartPoitners.  As 
soon as I try to use smart pointers, foward referencing seems to break.  
A declaration of type

    typedef typename ImageType::Pointer ImagePointer;

does not work because the compiler does not know that ::Pointer is part 
of class itk::Image.  Neither does the following declaration, which 
makes a forward reference to itk::SmartPointer:

namespace itk {
    ...
    template <class T> class SmartPointer;
};
...
    typedef typename itk::SmartPointer<ImageType> ImagePointer;
...

This does not work because the compiler can not allocate room for 
smartpointers without having seen them declared. If I do include the 
header itkSmartPointer.h, as in the following example, the code still 
does not work

#include <itkSmartPointer.h>
namespace itk {
    template <int i, class T> class Image;
    template <class TInput, class TOutput> class SomeFilter;
};

template <class TPixel> class Wrapper {
    typedef itk::Image<3,TPixel> ImageType;
    typedef typename itk::SmartPointer<ImageType> ImagePointer;
private:
    ImagePointer m_FirstImage,m_SecondImage; // and so on
};

This code does not compile (at least with VC60), and I get an error in 
itkSmartPoitner.h in the function Unregister().  This inline function 
can not be compiled using forward references to the class over which the 
SmartPointer is templated (in this case, itk::Image).  If I comment out 
the code in this function, the code does compile.  Curiously, the 
function Register() compiles just fine; the difference between them 
seems to come from the fact that UnRegister is used in the desctructor 
~SmartPointer(). 

Finally, I tried another solution, which does not use forward 
references.  I declared Wrapper as an abstract class with only virtual 
members and no attributes.  I declared a class WrapperImplementation 
that iherits from Wrapper and declares all the ITK SmartPointers and 
stuff.  The header for WrapperImplementation includes all the ITK 
headers.  I included "WrapperImplementation.h" only in the places in the 
code where new instances of WrapperImplementation are created.   This 
solution does not work well if I want to have an inheritance structure 
rooted at Wrapper: e.g., classes ColorWrapper and GreyWrapper that 
extend WrapperImplementation.  In order to declare these classes, I have 
to include "WrapperImplementation.h", and in order to use them 
throughout the application I would again end up including ITK headers in 
many places in the application.

So that's the dilemma, and my questions are

1. Has anyone been using forward references to ITK classes successfully?
2. Is there another way to avoid having to recompile lots of code when 
including ITK headers in widely used headers such as Wrapper.h?
3. Could the SmartPointer.h be modified to allow forward referencing?
4. There is a macro directive in the ITK .h files that allows manual 
instantiation of templates.  Can that be used across platforms?

Thank you very much for replying!

Paul.