[Insight-developers] IRIX64-6.5-CC-n32-Continuous errors and CastImageFilter (declaring specializations of member functions)

Miller, James V (Research) millerjv at crd . ge . com
Fri, 23 Aug 2002 16:04:31 -0400


The .Net compiler is not happy with these declarations of the specializations.



c:\projects\I2\Insight\Code\Numerics\FEM\itkFEMGenerateMesh.h(90) : error C2761: 'void
itk::fem::GenerateMesh<TElementType>::Rectangular(const
itk::fem::GenerateMesh<TElementType>::ElementType *,itk::fem::Solver
&,itk::fem::GenerateMesh<TElementType>::VectorType &,itk::fem::GenerateMesh<TElementType>::VectorType
&,itk::fem::GenerateMesh<TElementType>::VectorType &)' : member function redeclaration not allowed
        with
        [
            TElementType=itk::fem::Element2DC0LinearQuadrilateral
        ]

> -----Original Message-----
> From: Brad King [mailto:brad.king@kitware.com]
> Sent: Monday, August 05, 2002 6:34 PM
> To: Aljaz Noe
> Cc: 'Insight Developers'
> Subject: RE: [Insight-developers] IRIX64-6.5-CC-n32-Continuous errors
> and CastImageFilter
> 
> 
> Aljaz,
> 
> > I'm confused... Is this part of C++ specifications or a 
> 'feature' of SGI
> > compilers?
> 
> It is standard C++, SGI seems to be the only compiler that 
> enforces this
> behavior.
> 
> From paragraph 14.7.3/6 in the C++98 standard:
> 
> "If a template, a member template, or the member of a class 
> template is
> explicitly specialized then that specialization shall be 
> declared before
> the first use of that specialization that would cause implicit
> instantiation to take place, in every translation unit in 
> which such a use
> occurs; no diagnostic is required."
> 
> Since no diagnostic is required, most platforms don't report 
> this problem.
> SGI is kind enough to notice the problem and complain.
> 
> Here is the reason it is standard:
> 
> foo.h:
> 
> template <typename T>
> struct A { /* Generic implementation. */ };
> 
> foo1.cxx:
> 
> A<int> a1;  // Instantiates A<int> from primary template in foo.h
> 
> foo2.cxx:
> 
> template <>
> struct A<int> { /* Integer implementation. */ };
> 
> A<int> a2;  // Uses specialization.
> 
> foo3.cxx:
> 
> template <> struct A<int>;
> 
> A<int> a3;  // Uses specialization.  Linker will find symbols.
> 
> Now consider what happens when foo1.o, foo2.o, and foo3.o are linked.
> There are two definitions of the symbols from A<int>, and they are
> different.  This is because foo1 uses an instantiation of the primary
> template, while foo2 and foo3 use the speicalization.  This 
> will confuse
> the linker.  If instead the forward-declaration of the 
> specialization were
> in foo.h, all code would use the same symbols.  I can go into 
> more detail
> about linkers and weak v. strong symbols if you want.
> 
> > It seems that on all other platforms the compiler is able to
> > automatically find the class specializations provided by the code in
> > *.cxx file.
> 
> 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.
> 
> > Furthermore, forward declaring the template parameter 
> doesn't work. The
> > class used as a template parameter has to be completely declared (at
> > least the way class GenerateMesh is implemented now, because
> > GenerateMesh references one of its typedefs...).
> 
> 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.
> 
> > I implemented this class as templated one so that later, when new
> > elements are introduced, it should be quite simple to write 
> functions
> > that generate various types of meshes from these new elements in a
> > consistently way. Basically you just need to provide the 
> implementation
> > (specialization) of the member functions of GenerateMesh 
> class for the
> > specific element type without the need for changing the 
> existing library
> > code (file itkFEMGenerateMesh.h) and enforcing consistent syntax.
> >
> > The additional declaration of each specialized function in file
> > itkFEMGenerateMesh.h seems to defeat the purpose of using manual
> > specialization in the first place. Do you have any ideas, how these
> > things could be implemented in some other way?
> 
> 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).
> 
> -Brad
> 
> _______________________________________________
> Insight-developers mailing list
> Insight-developers@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-developers
>