Patch: Expanding Supported Explicit Instantiations

Jeffrey Oldham oldham at codesourcery.com
Fri May 25 17:44:33 UTC 2001


Dave Nystrom desired to explicitly instantiate this program:

    #include "Pooma/NewFields.h"
  
    #define T1 NoGeometry<(int)3>
    #define T2 int
    #define T3 CompressibleBrick
    #define T4 Interval<(int)3>
    template View1<Field<T1,T2,T3>,T4>::sv;

I do not know the correct syntax for explicitly instantiating View1's
const static bool `sv' if this is even legal.  The attached patch
permits instantiating

    #include "Pooma/NewFields.h"

    #define T1 NoGeometry<(int)3>
    #define T2 int
    #define T3 CompressibleBrick
    #define T4 Interval<(int)3>
    template class View1<Field<T1,T2,T3>,T4>;

It also permits

    template View0<Array<2,T2,T3> >;

without first explicitly instantiating Array<2,T2,T3>;

The main idea is to break mutually recursive class definitions by
defining alternative `View' classes that contain all the type
definitions of their corresponding `View' classes but omit the member
functions.  These alternative classes provide the return type for
non-templated member functions of Array and Field classes.  These
member functions' bodies still use the View classes.  Since the
alternative classes' definitions are the same as for the View classes,
this trickery works.  If a View class's code changes, the
corresponding alternative class's code must also be changed.  This
might lead to future maintenance problems.

Stephen Smith provided the insight for the patch so he deserves all
positive credit.  Send all criticisms to Jeffrey.

2001-05-25  Jeffrey D. Oldham <oldham at codesourcery.com>
	* Array/Array.h (View0): Modify initial comment to indicate
	changes should also be made to AltView0.
	(AltView0): New class to avoid explicit instantiation problems.
	(ComponentView): Modify initial comment to indicate class should
	not be explicitly instantiated.
	(Array::read()): Change return type to AltView0.
	(Array::operator()()): Likewise.

	* NewField/Field.h (View1Implementation): Modify initial comment
	to indicate changes should also be made to AltView1Implementation.
	(AltView1Implementation): New class to avoid explicit
	instantiation problems.
	(View1): Modify initial comment to indicate changes should also be
	made to AltView1.
	(AltView1): New class to avoid explicit instantiation problems.
	(Field::read()): Change return type to AltView1.
	(Field::readAll()): Likewise.
	(Field::read(s1)): Likewise.
	(Field::operator()()): Likewise.
	(Field::all()): Likewise.
	(Field::operator()(s1)): Likewise.

Tested on       sequential Linux using gcc 3.0
Approved by     Scott Haney

Thanks,
Jeffrey D. Oldham
oldham at codesourcery.com
-------------- next part --------------
Index: Array/Array.h
===================================================================
RCS file: /home/pooma/Repository/r2/src/Array/Array.h,v
retrieving revision 1.140
diff -c -p -r1.140 Array.h
*** Array/Array.h	2001/05/14 21:11:22	1.140
--- Array/Array.h	2001/05/25 17:37:49
*************** struct View1<Array<Dim, T, EngineTag>, D
*** 642,647 ****
--- 642,649 ----
  // an existing engine cannot be any kind of slice domain.
  // Also, bounds checking would make no sense because it would
  // reduce to contains(a.domain(), a.domain());
+ //
+ // Any changes to this class should also be made to AltView0.
  
  template<int Dim, class T, class EngineTag>
  struct View0<Array<Dim, T, EngineTag> >
*************** struct View0<Array<Dim, T, EngineTag> >
*** 686,691 ****
--- 688,728 ----
      }
  };
  
+ // AltView0 avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View0 except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ 
+ template<class ArrayTag>
+ struct AltView0;
+ 
+ template<int Dim, class T, class EngineTag>
+ struct AltView0<Array<Dim, T, EngineTag> >
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Array<Dim, T, EngineTag> Subject_t;
+ 
+   // Deduce domains for the output type.
+   // At some point, we need to fix NewDomain1; until then, use
+   // the temporary version from Array.h.
+   
+   typedef typename Subject_t::Engine_t Engine_t;
+   typedef typename Subject_t::Domain_t Domain_t;
+ 
+   // Deduce the template parameters for the output type.
+   
+   typedef typename NewEngine<Engine_t, Domain_t>::Type_t NewEngine_t;
+   enum { newDim = NewEngine_t::dimensions };
+   typedef typename NewEngine_t::Tag_t NewEngineTag_t;
+   
+   // The output types.
+   
+   typedef Array<newDim, T, NewEngineTag_t> Type_t;
+   typedef Type_t ReadType_t;
+ };
+ 
  template<int Dim, class T, class EngineTag>
  struct View1<Array<Dim, T, EngineTag>, int>
  {
*************** struct Patch<Array<Dim, T, EngineTag> >
*** 1278,1283 ****
--- 1315,1321 ----
  
  //-----------------------------------------------------------------------------
  // ComponentView specialization for Array.
+ // Changes to ComponentView should also be made to AltComponentView.
  //-----------------------------------------------------------------------------
  
  template<int Dim, class T, class EngineTag>
*************** struct ComponentView<Components, Array<D
*** 1314,1321 ****
  };
  
  //-----------------------------------------------------------------------------
! // AltComponentView gets around the problem that instantiation problem that
! // arises when two classes use each other.
  //-----------------------------------------------------------------------------
  
  template<class Components, class Arr>
--- 1352,1362 ----
  };
  
  //-----------------------------------------------------------------------------
! // AltComponentView avoids an instantiation problem that arises when
! // two classes use each other.  These classes' definitions should be
! // exactly the same as ComponentView except omitting member functions.
! //
! // Do NOT explicitly instantiate these alternative classes.
  //-----------------------------------------------------------------------------
  
  template<class Components, class Arr>
*************** public:
*** 1785,1791 ****
    // A zero-argument version of operator(), which takes a view of 
    // array's domain, is also supplied.
  
!   typename View0<This_t>::ReadType_t 
    read() const
      {
        typedef View0<This_t> Ret_t;
--- 1826,1832 ----
    // A zero-argument version of operator(), which takes a view of 
    // array's domain, is also supplied.
  
!   typename AltView0<This_t>::ReadType_t 
    read() const
      {
        typedef View0<This_t> Ret_t;
*************** public:
*** 1855,1861 ****
        return Ret_t::makeRead(*this, s1, s2, s3, s4, s5, s6, s7);
      }
  
!   typename View0<This_t>::Type_t 
    operator()() const
      {
        typedef View0<This_t> Ret_t;
--- 1896,1902 ----
        return Ret_t::makeRead(*this, s1, s2, s3, s4, s5, s6, s7);
      }
  
!   typename AltView0<This_t>::Type_t 
    operator()() const
      {
        typedef View0<This_t> Ret_t;
Index: NewField/Field.h
===================================================================
RCS file: /home/pooma/Repository/r2/src/NewField/Field.h,v
retrieving revision 1.13
diff -c -p -r1.13 Field.h
*** NewField/Field.h	2001/05/14 21:11:24	1.13
--- NewField/Field.h	2001/05/25 17:37:51
*************** public:
*** 187,192 ****
--- 187,195 ----
  // View1Implementation<Field, D, SV> specialization for indexing a field
  // with a single domain. There is a single-valued version (SV == true)
  // and a multi-valued version (SV == false).
+ //
+ // Any changes to View1Implementation should also be made to
+ // AltView1Implementation.
  //-----------------------------------------------------------------------------
  
  // Single-valued version. Handles scalars and Locs.
*************** struct View1Implementation<Field<Geometr
*** 423,429 ****
--- 426,487 ----
  
  
  //-----------------------------------------------------------------------------
+ // AltView1Implementation avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View1Implementation except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ //-----------------------------------------------------------------------------
+ 
+ // Single-valued version. Handles scalars and Locs.
+ 
+ template<class Subject, class Domain, bool SV>
+ struct AltView1Implementation;
+ 
+ template<class GeometryTag, class T, class EngineTag, class Domain>
+ struct AltView1Implementation<Field<GeometryTag, T, EngineTag>, Domain, true>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // The return types are pretty simple here.
+   
+   typedef typename Subject_t::Element_t ReadType_t;
+   typedef typename Subject_t::ElementRef_t Type_t;
+ };
+ 
+ template<class GeometryTag, class T, class EngineTag, class Domain>
+ struct AltView1Implementation<Field<GeometryTag, T, EngineTag>, Domain, false>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // Deduce domains for the output type.
+   
+   typedef typename Subject_t::Engine_t Engine_t;
+   typedef typename NewEngine<Engine_t, Domain>::Type_t NewEngine_t;
+   typedef typename NewEngine_t::Element_t NewT_t;
+   typedef typename NewEngine_t::Tag_t NewEngineTag_t;
+   
+   // Deduce the new GeometryTag.
+   
+   typedef typename
+     NewGeometryTag<NewEngine_t::dimensions, GeometryTag, Domain>::Type_t 
+       NewGeometryTag_t;
+   
+   // The output types.
+   
+   typedef Field<NewGeometryTag_t, NewT_t, NewEngineTag_t> ReadType_t;
+   typedef Field<NewGeometryTag_t, NewT_t, NewEngineTag_t> Type_t;
+ };
+ 
+ 
+ //-----------------------------------------------------------------------------
  // View1<Field, S1> specialization for indexing a field with a single domain.
+ //
+ // Any changes to View1 should also be made to AltView1.
  //-----------------------------------------------------------------------------
  
  template<class GeometryTag, class T, class EngineTag, class Sub1>
*************** struct View1<Field<GeometryTag, T, Engin
*** 473,478 ****
--- 531,538 ----
  
  //-----------------------------------------------------------------------------
  // View1<Field, int> specialization for indexing a field with an int.
+ //
+ // Any changes to View1 should also be made to AltView1.
  //-----------------------------------------------------------------------------
  
  template<class GeometryTag, class T, class EngineTag>
*************** struct View1<Field<GeometryTag, T, Engin
*** 516,521 ****
--- 576,711 ----
  
  
  //-----------------------------------------------------------------------------
+ // AltView1 avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View1 except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ //-----------------------------------------------------------------------------
+ 
+ template<class FieldTag, class DomainTag>
+ struct AltView1;
+ 
+ template<class GeometryTag, class T, class EngineTag, class Sub1>
+ struct AltView1<Field<GeometryTag, T, EngineTag>, Sub1>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // Deduce domains for the output type.
+   // At some point, we need to fix NewDomain1; until then, use
+   // the temporary version from NewDomain.h.
+   
+   typedef typename Subject_t::Domain_t Domain_t;
+   typedef TemporaryNewDomain1<Domain_t, Sub1> NewDomain_t;
+   typedef typename NewDomain_t::SliceType_t SDomain_t;
+   
+   // Deduce appropriate version of implementation to dispatch to.
+   
+   static const bool sv = DomainTraits<SDomain_t>::singleValued;
+   typedef AltView1Implementation<Subject_t, SDomain_t, sv> Dispatch_t;
+ 
+   // The optimized domain combiner.
+   
+   typedef CombineDomainOpt<NewDomain_t, sv> Combine_t;
+   
+   // The return types.
+   
+   typedef typename Dispatch_t::ReadType_t ReadType_t;
+   typedef typename Dispatch_t::Type_t Type_t;
+ };
+ 
+ 
+ //-----------------------------------------------------------------------------
+ // AltView1 avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View1 except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ //-----------------------------------------------------------------------------
+ 
+ template<class GeometryTag, class T, class EngineTag>
+ struct AltView1<Field<GeometryTag, T, EngineTag>, int>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // The return types.
+   
+   typedef typename Subject_t::Element_t ReadType_t;
+   typedef typename Subject_t::ElementRef_t Type_t;
+ 
+ };
+ 
+ 
+ //-----------------------------------------------------------------------------
+ // AltView1 avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View1 except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ //-----------------------------------------------------------------------------
+ 
+ template<class FieldTag, class DomainTag>
+ struct AltView1;
+ 
+ template<class GeometryTag, class T, class EngineTag, class Sub1>
+ struct AltView1<Field<GeometryTag, T, EngineTag>, Sub1>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // Deduce domains for the output type.
+   // At some point, we need to fix NewDomain1; until then, use
+   // the temporary version from NewDomain.h.
+   
+   typedef typename Subject_t::Domain_t Domain_t;
+   typedef TemporaryNewDomain1<Domain_t, Sub1> NewDomain_t;
+   typedef typename NewDomain_t::SliceType_t SDomain_t;
+   
+   // Deduce appropriate version of implementation to dispatch to.
+   
+   static const bool sv = DomainTraits<SDomain_t>::singleValued;
+   typedef View1Implementation<Subject_t, SDomain_t, sv> Dispatch_t;
+ 
+   // The optimized domain combiner.
+   
+   typedef CombineDomainOpt<NewDomain_t, sv> Combine_t;
+   
+   // The return types.
+   
+   typedef typename Dispatch_t::ReadType_t ReadType_t;
+   typedef typename Dispatch_t::Type_t Type_t;
+ };
+ 
+ 
+ //-----------------------------------------------------------------------------
+ // AltView1 avoids an instantiation problem that arises when two
+ // classes use each other.  This class's definition should be exactly
+ // the same as View1 except omitting member functions.
+ //
+ // Do NOT explicitly instantiate this class.
+ //-----------------------------------------------------------------------------
+ 
+ template<class GeometryTag, class T, class EngineTag>
+ struct AltView1<Field<GeometryTag, T, EngineTag>, int>
+ {
+   // Convenience typedef for the thing we're taking a view of.
+   
+   typedef Field<GeometryTag, T, EngineTag> Subject_t;
+ 
+   // The return types.
+   
+   typedef typename Subject_t::Element_t ReadType_t;
+   typedef typename Subject_t::ElementRef_t Type_t;
+ 
+ };
+ 
+ 
+ //-----------------------------------------------------------------------------
  // View2<Field, S1, S2> specialization for indexing a field with two
  // domains.
  //-----------------------------------------------------------------------------
*************** public:
*** 1010,1023 ****
    // version returns a view of the physical domain and the 'All'-suffixed
    // versions return a view of the total domain.
  
!   inline typename View1<This_t, Domain_t>::ReadType_t 
    read() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
        return Ret_t::makeRead(*this, physicalDomain());
      }
  
!   inline typename View1<This_t, Domain_t>::ReadType_t 
    readAll() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
--- 1200,1213 ----
    // version returns a view of the physical domain and the 'All'-suffixed
    // versions return a view of the total domain.
  
!   inline typename AltView1<This_t, Domain_t>::ReadType_t 
    read() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
        return Ret_t::makeRead(*this, physicalDomain());
      }
  
!   inline typename AltView1<This_t, Domain_t>::ReadType_t 
    readAll() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
*************** public:
*** 1025,1031 ****
      }
  
    template<class Sub1> 
!   inline typename View1<This_t, Sub1>::ReadType_t 
    read(const Sub1 &s1) const
      {
        typedef View1<This_t, Sub1> Ret_t;
--- 1215,1221 ----
      }
  
    template<class Sub1> 
!   inline typename AltView1<This_t, Sub1>::ReadType_t 
    read(const Sub1 &s1) const
      {
        typedef View1<This_t, Sub1> Ret_t;
*************** public:
*** 1048,1061 ****
        return Ret_t::makeRead(*this, s1, s2, s3);
      }
  
!   inline typename View1<This_t, Domain_t>::Type_t 
    operator()() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
        return Ret_t::make(*this, physicalDomain());
      }
  
!   inline typename View1<This_t, Domain_t>::Type_t 
    all() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
--- 1238,1251 ----
        return Ret_t::makeRead(*this, s1, s2, s3);
      }
  
!   inline typename AltView1<This_t, Domain_t>::Type_t 
    operator()() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
        return Ret_t::make(*this, physicalDomain());
      }
  
!   inline typename AltView1<This_t, Domain_t>::Type_t 
    all() const
      {
        typedef View1<This_t, Domain_t> Ret_t;
*************** public:
*** 1063,1069 ****
      }
  
    template<class Sub1> 
!   inline typename View1<This_t, Sub1>::Type_t 
    operator()(const Sub1 &s1) const
      {
        typedef View1<This_t, Sub1> Ret_t;
--- 1253,1259 ----
      }
  
    template<class Sub1> 
!   inline typename AltView1<This_t, Sub1>::Type_t 
    operator()(const Sub1 &s1) const
      {
        typedef View1<This_t, Sub1> Ret_t;


More information about the pooma-dev mailing list