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