Listing G
////////////////////////////////////////////////
// dependent_static.h
#ifndef DEPENDENT_STATIC__H
#define DEPENDENT_STATIC__H
 
#include <assert.h>
#include <vector>
#include <algorithm>
#include <stdexcept>
 
namespace Private
{
    class no_type {};
 
    struct no_type_as_param {
        no_type_as_param( no_type &) {}
    };
    template< class type> struct ref_wrapper
    {
        ref_wrapper( type & val) : m_ref( val) {}
        type & m_ref;
    };
 
    // transform no_type into no_type_as_param
    // the rest is transformed into ref_wrapper
    template< class type>
        struct type_as_param_impl { typedef ref_wrapper< type> result; };
    template<>
        struct type_as_param_impl< no_type> { typedef no_type_as_param result; };
 
    // transforms no_type into no_type_as_param;
    // anything else (T) is transformed into ref_wrapper< T>
    template< class type>
        inline typename type_as_param_impl< type>::result  type_as_param( type & val) { return val; }
 
 
    // 2 Params
    template< class type, class type01, class type02 >
    inline void call_initializer_impl( type * & p,
        ref_wrapper< type01> val01, ref_wrapper< type02> val02 )
    {
        p = new type( val01.m_ref, val02.m_ref );
    }
 
    // 1 Param
    template< class type, class type01 >
    inline void call_initializer_impl( type * & p,
        ref_wrapper< type01> val01, no_type_as_param )
    {
        p = new type( val01.m_ref );
    }
 
    // 0 Params
    template< class type>
    inline void call_initializer_impl( type * & p,
        no_type_as_param, no_type_as_param )
    {
        p = new type();
    }
 
    // delegate to call_initializer_impl
    template<
        class type,
        class type01 ,
        class type02>
    inline void call_initializer( type * & p,
         type01 & val01 ,
         type02 & val02)
    {
        call_initializer_impl( p,
            type_as_param( val01), type_as_param( val02) );
    }
 
 
} // namespace Private
 
 
 
template< class type>
struct collect_parameters_base
{
    //initializes this pointer
    virtual void initialize(type * & p) = 0;
};
 
 
template<
        class type,
        class type01 = Private::no_type,
        class type02 = Private::no_type>
struct collect_parameters :
    public collect_parameters_base< type>
{
    collect_parameters(
        // we pass params by value - this way,
        // we can even pass functions as arguments!
        type01 val01 = type01(),
        type02 val02 = type02() )
        :  m_val01( val01),
            m_val02( val02)
    {}
 
    void initialize(type * & p)
    {
        // we're initializing p now!!!
        assert( p == 0);
        Private::call_initializer( p,
            m_val01,
            m_val02);
    }
 
private:
    type01 m_val01;
    type02 m_val02;
};
 
 
 
// function new_collect_parameters:
// returns a new collect_parameters object,
// based on its arguments
template<
    class type,
    class type01 ,
    class type02 >
inline collect_parameters_base< type> *
    new_collect_parameters(
        type01 val01 ,
        type02 val02)
{
    return new collect_parameters<type, type01, type02>( val01, val02);
}
 
 
namespace Private
{
    // forward declaration
    struct dependent_static_base;
}
 
 
class all_dependent_statics
{
    // don't allow creation except for our instance()
    all_dependent_statics() {}
public:
    void add_dependent_static( Private::dependent_static_base * p)
    { m_aStatics.push_back( p); }
 
    inline static void initialize_statics();
    inline static all_dependent_statics & instance()
    { static all_dependent_statics inst; return inst; }
private:
    std::vector< Private::dependent_static_base*> m_aStatics;
};
 
 
namespace Private
{
    struct dependent_static_base
    {
        dependent_static_base()
        { ::all_dependent_statics::instance().add_dependent_static( this); }
        virtual void initialize_static() = 0;
    };
 
    // helper
    inline void do_initialize_static( dependent_static_base *p)
    { p->initialize_static(); }
};
 
// initialize our statics
inline void all_dependent_statics::initialize_statics()
{
    all_dependent_statics & inst = all_dependent_statics::instance();
    std::for_each( inst.m_aStatics.begin(), inst.m_aStatics.end(), Private::do_initialize_static);
}
 
 
/*
    postpones initialization of static variable
    (it's initialized when you call initialize_static)
*/
struct dependent_static :
    // so that we can register this object, to be initialized later
    private Private::dependent_static_base
{
    // non-copyiable
    typedef dependent_static< type> this_class;
    dependent_static( const this_class &);
    this_class operator=( const this_class &);
 
public:
 
    // 2 Params
    template< class type01, class type02 >
    dependent_static( type01 val01, type02 val02)
    : m_pVal( 0),
      m_pInitializer( new_collect_parameters< type>( val01, val02)) {}
 
    // 1 Param
    template< class type01 >
    dependent_static( type01 val01)
    : m_pVal( 0),
      m_pInitializer( new_collect_parameters< type>( val01,  Private::no_type() )) {}
 
    // 0 Params
    dependent_static()
    : m_pVal( 0),
      m_pInitializer( new_collect_parameters< type>( Private::no_type(), Private::no_type() )) {}
 
    ~dependent_static() { delete m_pInitializer; }
 
    /* virtual */ void initialize_static()
    {
        if ( m_pVal == 0)
            m_pInitializer->initialize( m_pVal);
        else
            // already initialized!!!
            assert( false);
    }
 
    operator type &()
    { check_val(); return *m_pVal; }
    operator const type&() const
    { check_val(); return *m_pVal; }
 
private:
    void check_val() const
    {
        if ( m_pVal == 0)
            throw std::runtime_error( "dependent_static used too early!"
            " (before calling 'all_dependent_statics::initialize_statics()' )");
    }
 
private:
    collect_parameters_base< type> *m_pInitializer;
    type * m_pVal;
}; // dependent_static
 
 
#endif // DEPENDENT_STATIC__H