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