[Insight-developers] IRIX64-6.5-CC-n32-Continuous errors and CastImageFilter

Aljaz Noe noe at grasp . cis . upenn . edu
Mon, 5 Aug 2002 21:06:40 -0400


> It is standard C++, SGI seems to be the only compiler that 
> enforces this behavior.
> ...
> I can go into more detail
> about linkers and weak v. strong symbols if you want.

Thanks for the info. The whole things seems a lot clearer to me now.
Believe it or not, I'm interested in that kind of stuff...

> You've gotten lucky so far.  The current situation doesn't 
> involve all the
> components of the above example, but it could easily do so in 
> the future.

I understand. There is no code for that member function that could be
implicitly specialized, so there is nothing compiler can do, and it's
totally up to the linker to find the correct implementation of a
function somewhere else. That's basically how I wanted it to be. I don't
want any implicit specialization, for any template parameter.

I wondered if the following 'templated' declaration of member function
would make SGIs happy, but it turns out, it makes MSVC cry. So I guess
it't not so important. It works on Intel C++ 6.0, though.

A.h:

template<class T>
class A
{ f(); }

template<class T>
A<T>::F(); // explicitly declare the the member funtion for all classes


A.cxx:

template<>
A<int>::f() { ... }


> True, I didn't notice that.  You can, however, avoid the 
> typedef lookup by
> simply using "const ElementType*" instead of 
> "ElementType::ConstPointer".
> This is actually preferable as it is ITK standard to pass raw 
> pointers as
> function arguments instead of smart pointers.  In this case it won't
> change anything since ElementType::ConstPointer isn't a smart pointer
> anyway.

That's an ITK's standard??? Why didn't anybody tell me this 6 months ago
when I spent quite some time making the whole FEM code using T::Pointer
instead T*... Originally everything was written using the T* syntax for
pointers. And it worked, and it was much simpler, too...

> This approach is known as a "trait".  Traits are used when most of the
> implementation of a class over two types is the same, but 
> small sections
> differ.  The code for sections that differ is looked up 
> through a "trait"
> class that can be programmed on a per-type basis using template
> specialization.
> 
> Your implementation of traits is different from the usual way 
> we use in
> ITK.  In this case, it looks like GenerateMesh is basically a 
> trait class
> in itself.  You might look at writing it this way:
> 
> itkFEMGenerateMesh.h:
> 
> // Empty primary template:
> template <typename TElementType> class GenerateMesh;
> 
> // Specialization of entire class for Element2DC0LinearQuadrilateral:
> class Element2DC0LinearQuadrilateral;
> template<>
> class GenerateMesh<Element2DC0LinearQuadrilateral>
> {
>   typedef Element2DC0LinearQuadrilateral ElementType;
>   typedef vnl_vector<ElementType> VectorType;
>   static void Rectangular(const ElementType* e0,
>                           Solver& S,
>                           VectorType& orig,
>                           VectorType& size,
>                           VectorType& Nel);
> };
> 
> // Other specializations...
> 
> itkFEMGenerateMesh.cxx:
> 
> // Implement specializations:
> void
> GenerateMesh<Element2DC0LinearQuadrilateral>
> ::Rectangular(ElementType::ConstPointer e0, Solver& S, 
> VectorType& orig,
>               VectorType& size, VectorType& Nel)
> {
>   /* ... */
> }
> 
> This version requires a little more code, but it is more 
> consistent with
> other traits in ITK, and will be more easily understood by most
> programmers (I think).

That's basically how I wanted to implement the whole meshing class in
the first try. But then  I changed my mind. In general, we can have
several types of meshes. Some day somebody will want to create a
Spherical mesh, for example. By the time that happens, somebody else
will already have written implementations of Rectangular function for
several different element classes. And all these class specializations
would have to be updated to include the new Sperical member function (if
required, of course).

Using the approach I chose, I only need to update the
itkFEMGenerateMesh.h by adding the declaration of the Spherical function
and writing (zero or more) implementatons for different Element classes.
Everything else remains the same. Even more... I can even use the
complete class specialization (like your example) to add new functions
to GenerateMesh without touching the existing GenerateMesh template. In
addition, the declaration of all the meshing functions declared in
itkFEMGenerateMesh.h (Rectangular, Sperical, ...) is implicitly the same
for all elements.

That's the reason I used this 'funky' way of defining the GenerateMesh
class.

Aljaz