[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:18:55 -0400


Looking further at this... Why even have this as a class? All it has is a 
static member function.  There is no instance data or regular member functions.

Why not have this be a templated or just an overloaded (regular not class) function?


> -----Original Message-----
> From: Miller, James V (Research) 
> Sent: Friday, August 23, 2002 4:05 PM
> To: 'Brad King'; Aljaz Noe
> Cc: 'Insight Developers'
> Subject: RE: [Insight-developers] IRIX64-6.5-CC-n32-Continuous errors
> and CastImageFilter (declaring specializations of member functions)
> 
> 
> 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
> > 
> _______________________________________________
> Insight-developers mailing list
> Insight-developers@public.kitware.com
> http://public.kitware.com/mailman/listinfo/insight-developers
>