PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 1/7 TITLE : Class templates and nested classes //----------------------------------------------------------- // // Class templates and nested classes. // // In accordance with Bjarne Stroustrup's The C++ Programming // Language, 2nd edition, class templates must be declared at // global scope; thus, you cannot define a class template // nested within a class template. It is legal to define a // non-template class nested within a class template. While // Borland C++ 3.1 does support this syntax, it does not // support out-of-line definition of methods of the nested // class. This document shows an implementation of a nested // class which conforms to the requirement for only inline // member functions and an alternative design allowing for // out-of-line definition of inline and non-inline members. // // Note: There is some question as to whether the final ANSI // specification for C++ will mandate support for out-of-line // definition of methods of a class nested in a template // class. If supported, the syntax should be: // // template< class T > // void TemplateClass< T >::NestedClass::Method( void ) // { // } // //----------------------------------------------------------- //----------------------------------------------------------- // // NesTemp1.cpp // // This first design is a simple Queue structure containing a // nested Node structure. By nesting the Node structure, it // is effectively a template itself and appropriately adjusts // to the type for which the Queue is instantiated. // //----------------------------------------------------------- #include #include PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 2/7 TITLE : Class templates and nested classes // // class Queue - note that the Node class knows about the // type for which the Queue class has been instantiated and // can use that information. // template< class T > class Queue { public: Queue(); ~Queue(); int Put( T newData ); T Get( void ); operator int() { return( head != NULL ); } private: class Node { public: T data; Node * next; Node( T theData ) : data( theData ), next( NULL ) {} }; Node * head, * tail; }; // // Out-of-line definition of an inline member of a class // template. // template< class T > inline Queue< T >::Queue() : head( 0 ), tail( 0 ) { } // // Clean up any remaining nodes. Note that the Queue does not // own the data in the nodes, so the data objects are not // cleaned up. // template< class T > Queue< T >::~Queue() { Node * temp; PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 3/7 TITLE : Class templates and nested classes while( head ) { temp = head; head = head->next; delete temp; } } // // Add a node containing the new data. // template< class T > int Queue< T >::Put( T newData ) { Node * temp = new Node( newData ); if( !temp ) return 0; if( head ) { tail->next = temp; tail = temp; } else { head = tail = temp; } return 1; } // // Delete the node and return the data. // template< class T > T Queue< T >::Get( void ) { T data = head->data; Node * node = head; head = ( head == tail ) ? ( tail = 0 ) : ( head->next ); delete node; return data; } // // A simple test. Command line arguments are put into the PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 4/7 TITLE : Class templates and nested classes // Queue and then retrieved and displayed. // int main( int argc, char ** argv ) { Queue< char * > queue; for( int i = 0; i #include // // A forward declaration of class Queue allows us to declare // it a friend of class Node. // template< class T > class Queue; // // The Node class is itself a template class, allowing it to // handle various types of the container Queue. Since the // class declaration is no longer private to class Queue, it // now seems appropriate to provide an access member for the // data. Note that although the Node class is no longer PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 5/7 TITLE : Class templates and nested classes // nested, all members are private and therefore it has the // same status - it is useless outside Queue. // template< class T > class Node { private: T data; Node * next; Node( T theData ); friend class Queue< T >; }; // // Inline and non-inline members of Node can now be defined // out-of-line. // template< class T > inline Node< T >::Node( T theData ) : data( theData ), next( NULL ) { } // // Since the head and tail are pointers to Nodes instantiated // for the same type as the Queue class, the same effect as a // nested class is easy to achieve. // template< class T > class Queue { public: Queue(); ~Queue(); int Put( T newData ); T Get( void ); operator int() { return( head != NULL ); } private: Node< T > * head, * tail; }; // // Out-of-line definition of an inline member of a class // template. // PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 6/7 TITLE : Class templates and nested classes template< class T > inline Queue< T >::Queue() : head( 0 ), tail( 0 ) { } // // Clean up any remaining nodes. Note that the Queue does not // own the data in the nodes, so the data objects are not // cleaned up. // template< class T > Queue< T >::~Queue() { Node< T > * temp; while( head ) { temp = head; head = head->next; delete temp; } } // // Add a node containing the new data. // template< class T > int Queue< T >::Put( T newData ) { Node< T > * temp = new Node< T >( newData ); if( !temp ) return 0; if( head ) { tail->next = temp; tail = temp; } else { head = tail = temp; } return 1; } // PRODUCT : Borland C++ NUMBER : 1702 VERSION : All OS : All DATE : October 25, 1993 PAGE : 7/7 TITLE : Class templates and nested classes // Delete the node and return the data. // template< class T > T Queue< T >::Get( void ) { T data = head->data; Node< T > * node = head; head = ( head == tail ) ? ( tail = 0 ) : ( head->next ); delete node; return data; } // // A simple test. Command line arguments are put into the // Queue and then retrieved and displayed. // int main( int argc, char ** argv ) { Queue< char * > queue; for( int i = 0; i