[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
>