The following does not compile with g++ 3.4.2 on Solaris and 3.2.3 on Linux, but probably should, and does with other compilers.
class PropertyId; class ArraySegment; class StringSegment; class EnumStateSet; class PropertyCatalog; class PropertyCatalog; class Time; class PropertyId { }; extern class PropertyCatalog & voidContainer; template < template < class T > class PROPERTY > class PropertyManipulator { public: virtual void reveal ( PROPERTY < float > & ) = 0; virtual void reveal ( PROPERTY < double > & ) = 0; virtual void reveal ( PROPERTY < char > & ) = 0; virtual void reveal ( PROPERTY < signed char > & ) = 0; virtual void reveal ( PROPERTY < unsigned char > & ) = 0; virtual void reveal ( PROPERTY < short > & ) = 0; virtual void reveal ( PROPERTY < unsigned short > & ) = 0; virtual void reveal ( PROPERTY < int > & ) = 0; virtual void reveal ( PROPERTY < unsigned int > & ) = 0; virtual void reveal ( PROPERTY < long > & ) = 0; virtual void reveal ( PROPERTY < unsigned long > & ) = 0; virtual void reveal ( PROPERTY < Time > & ) = 0; virtual void reveal ( PROPERTY < StringSegment > & ) = 0; virtual void reveal ( PROPERTY < EnumStateSet > & ) = 0; virtual void reveal ( PROPERTY < ArraySegment > & ) = 0; virtual void reveal ( PROPERTY < PropertyCatalog > & ) = 0; }; template < class CATALOG > class PropertyBase { public: PropertyBase ( const PropertyId & id, CATALOG & subordinate ); const PropertyId & id () const; CATALOG & subordinate () const; private: const PropertyId & _id; CATALOG & _subordinateProperties; }; template < class T > class PropertyType : public PropertyBase < const PropertyCatalog > { public: PropertyType ( const PropertyId & id, const PropertyCatalog & = voidContainer ); template < class C > PropertyType ( const PropertyId & id, const C * pC, T ( C :: * p ), const PropertyCatalog & subordinate = voidContainer ); }; template < class T > class PropertyMutable : public PropertyBase < PropertyCatalog > { public: PropertyMutable ( const PropertyId & id, T & value, PropertyCatalog & subordinate = voidContainer ); template < class C > PropertyMutable ( const PropertyId & id, C * pC, T ( C :: * p ), PropertyCatalog & subordinate = voidContainer ); T & value (); private: T & _scalar; }; template < class T > class PropertyImmutable : public PropertyBase < const PropertyCatalog > { public: PropertyImmutable ( const PropertyId & id, const T & value, const PropertyCatalog & subordinate = voidContainer ); template < class C > PropertyImmutable ( const PropertyId & id, const C * pC, T ( C :: * p ), const PropertyCatalog & subordinate = voidContainer ); const T & value () const; private: const T & _scalar; }; class PropertySkeleton { public: virtual void traverse ( PropertyManipulator < PropertyType > & ) = 0; }; class PropertyCatalog { public: virtual void traverse ( PropertyManipulator < PropertyMutable > & ) = 0; virtual void traverse ( PropertyManipulator < PropertyImmutable > & ) const = 0; // false returned when the property does not exist, otherwise true virtual bool find ( const PropertyId & id, PropertyManipulator < PropertyImmutable > & ) const = 0; }; // ----------------- begin property implementation ---------------------------------- class VoidContainer : public PropertyCatalog { void traverse ( PropertyManipulator < PropertyMutable > & ) {} void traverse ( PropertyManipulator < PropertyImmutable > & ) const {} // false returned when the property does not exist, otherwise true bool find ( const PropertyId & id, PropertyManipulator < PropertyImmutable > & ) const { return false; } }; VoidContainer aVoidContainer; class PropertyCatalog & voidContainer = aVoidContainer; template < class CATALOG > inline PropertyBase < CATALOG > :: PropertyBase ( const PropertyId & id, CATALOG & subordinate ) : _id ( id ), _subordinateProperties ( subordinate ) { } template < class CATALOG > inline const PropertyId & PropertyBase < CATALOG > :: id () const { return _id; } template < class CATALOG > inline CATALOG & PropertyBase < CATALOG > :: subordinate () const { return _subordinateProperties; } template < class T > inline PropertyType < T > :: PropertyType ( const PropertyId & id, const PropertyCatalog & subordinate ) : PropertyBase < const PropertyCatalog > ( id, subordinate ) { } template < class T > template < class C > inline PropertyType < T > :: PropertyType ( const PropertyId & id, const C *, T ( C :: * ), const PropertyCatalog & subordinate ) : PropertyBase < const PropertyCatalog > ( id, subordinate ) { } template < class T > inline PropertyMutable < T > :: PropertyMutable ( const PropertyId & id, T & value, PropertyCatalog & subordinate ) : PropertyBase < PropertyCatalog > ( id, subordinate ), _scalar ( value ) { } template < class T > template < class C > inline PropertyMutable < T > :: PropertyMutable ( const PropertyId & id, C * pC, T ( C :: * p ), PropertyCatalog & subordinate ) : PropertyBase < PropertyCatalog > ( id, subordinate ), _scalar ( pC->*p ) { } template < class T > inline T & PropertyMutable < T > :: value () { return _scalar; } template < class T > inline PropertyImmutable < T > :: PropertyImmutable ( const PropertyId & id, const T & value, const PropertyCatalog & subordinate ) : PropertyBase < const PropertyCatalog > ( id, subordinate ), _scalar ( value ) { } template < class T > template < class C > inline PropertyImmutable < T > :: PropertyImmutable ( const PropertyId & id, const C * pC, T ( C :: * p ), const PropertyCatalog & subordinate ) : PropertyBase < const PropertyCatalog > ( id, subordinate ), _scalar ( pC->*p ) { } template < class T > inline const T & PropertyImmutable < T > :: value () const { return _scalar; } // --------------------------- begin application specific ------------- PropertyId propertyX; PropertyId propertyY; class MyContainerSkeleton : public PropertySkeleton { public: void traverse ( PropertyManipulator < PropertyType > & ); }; class MyContainer : public PropertyCatalog, public MyContainerSkeleton { public: void traverse ( PropertyManipulator < PropertyMutable > & ); void traverse ( PropertyManipulator < PropertyImmutable > & ) const; static void traverseTypes ( PropertyManipulator < PropertyType > & ); bool find ( const PropertyId & id, PropertyManipulator < PropertyImmutable > & ) const; private: int x; float y; template < class C, template < class T > class PROPERTY > static void traverseTempl ( C * pContainer, PropertyManipulator < PROPERTY > & ); }; // C is a template purely so that we can reveal const and non-const // using the same template, but perhaps there is another way template < class C, template < class T > class PROPERTY > void MyContainer::traverseTempl ( C * pContainer, PropertyManipulator < PROPERTY > & manipulator ) { manipulator.reveal ( PROPERTY < int > ( propertyX, pContainer, & MyContainer::x ) ); manipulator.reveal ( PROPERTY < float > ( propertyY, pContainer, & MyContainer::y ) ); } void MyContainer::traverse ( PropertyManipulator < PropertyMutable > & manipulator ) { MyContainer::traverseTempl ( this, manipulator ); } void MyContainer::traverse ( PropertyManipulator < PropertyImmutable > & manipulator ) const { MyContainer::traverseTempl ( this, manipulator ); } void MyContainerSkeleton::traverse ( PropertyManipulator < PropertyType > & manipulator ) { MyContainer::traverseTypes ( manipulator ); } void MyContainer::traverseTypes ( PropertyManipulator < PropertyType > & manipulator ) { const MyContainer * pC = 0; MyContainer::traverseTempl ( pC, manipulator ); } MyContainer mc; -- Summary: template template parameter function overload not recognized Product: gcc Version: 3.4.2 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: johill at lanl dot gov CC: gcc-bugs at gcc dot gnu dot org GCC host triplet: solaris/sparc also earlier version on Linux GCC target triplet: solaris/sparc also earlier version on Linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21665