|
#ifndef DECORATORCHAIN_H_
#define DECORATORCHAIN_H_
#include <vector>
#include <stdexcept>
// Compile-time switch for decorators decorating references or pointers
struct reference_decorator_category { };
struct pointer_decorator_category { };
template< class Class , class DecoratorCategory = pointer_decorator_category >
class decorator_chain
{
public:
typedef Class class_type;
typedef DecoratorCategory category_type;
decorator_chain( bool owner_of_class = false , bool owner_of_decorators = false )
: m_class_instance( 0 ) , m_decorators() , m_current( 0 ) ,
m_owner_of_class( owner_of_class ) , m_owner_of_decorators( owner_of_decorators )
{
}
~decorator_chain( void )
{
if( m_owner_of_class )
{
if( m_class_instance != 0 )
{
delete m_class_instance;
m_class_instance = 0;
}
}
if( m_owner_of_decorators )
{
for( size_t i=0 ; i<m_decorators.size() ; ++i )
{
delete m_decorators[i];
m_decorators[i] = 0;
}
}
}
template< class Factory >
void create_class( Factory make_class = Factory() )
{
if( m_class_instance != 0 ) throw std::logic_error( "Object already created!" );
m_class_instance = make_class();
m_current = m_class_instance;
}
template< class Factory >
void decorate( Factory make_class = Factory() )
{
if( m_current == 0 ) throw std::logic_error( "Object has not been created!" );
class_type *decorator = create_by_category( make_class , category_type() );
m_decorators.push_back( decorator );
m_current = decorator;
}
class_type& get_class_reference( void ) { return *m_current; }
const class_type& get_class_reference( void ) const { return *m_current; }
class_type* get_class_pointer( void ) { return m_current; }
const class_type* get_class_pointer( void ) const { return m_current; }
private:
class_type *m_class_instance;
std::vector< class_type* > m_decorators;
class_type *m_current;
bool m_owner_of_class;
bool m_owner_of_decorators;
template< class Factory >
class_type* create_by_category( Factory factory , reference_decorator_category )
{
return factory( *m_current );
}
template< class Factory >
class_type* create_by_category( Factory factory , pointer_decorator_category )
{
return factory( m_current );
}
};
#endif /* DECORATORCHAIN_H_ */
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.