Vous pouvez utiliser un pointeur intelligent de votre propre conception qui le commet lors de la première déréférence (en surchargeant bien sûr les opérateurs de déréférence et d'indirection).
Il s'agit d'un exemple de pointeur intelligent qui crée une instance d'un objet donné lors de la première déréférence (instanciation paresseuse). Même idée, en gros :
template <typename T>
struct default_constructor_factory
{
T * operator ()() { return new T; }
};
template <typename T, typename F = default_constructor_factory<T> >
class lazy_ptr : boost::noncopyable
{
public:
typedef T element_type;
typedef T value_type;
typedef F factory_type;
typedef lazy_ptr<T,F> this_type;
lazy_ptr() : m_ptr(), m_factory() { }
lazy_ptr(F factory) : m_ptr(), m_factory(factory) { }
~lazy_ptr() { if (m_ptr != NULL) delete m_ptr; }
T & operator* () const
{
return *get();
}
T * operator-> () const
{
return get();
}
T * get() const
{
if (m_ptr == NULL)
m_ptr = m_factory();
return m_ptr;
}
void reset(T * p)
{
if (p != m_ptr)
{
if (m_ptr != NULL)
delete m_ptr;
m_ptr = p;
}
}
T * release()
{
T * p = m_ptr;
m_ptr = NULL;
return p;
}
// non-dereferencing accessors
T * peek() const
{
// may return NULL
return m_ptr;
}
bool dereferenced() const
{
return peek() != NULL;
}
// operator bool() const { return dereferenced(); }
// handle intrinsic conversion to testable bool using unspecified_bool technique
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return dereferenced() ? &this_type::m_ptr : NULL;
}
private:
// we must remain it's only owner!
mutable T * m_ptr;
// our factory generates the needed element on-demand
mutable factory_type m_factory;
};
// shared_lazy_ptr
//
// we act as a copyable lazy pointer
// essentially, we add reference counting to a single shared lazy pointer
//
template <typename T, typename F = default_constructor_factory<T> >
class shared_lazy_ptr
{
public:
typedef T element_type;
typedef T value_type;
typedef F factory_type;
typedef lazy_ptr<T,F> ptr_type;
typedef shared_lazy_ptr<T,F> this_type;
shared_lazy_ptr() : m_ptr(new ptr_type) { }
shared_lazy_ptr(F factory) : m_ptr(new ptr_type(factory)) { }
// copy ctor
shared_lazy_ptr(const this_type & rhs) : m_ptr(rhs.m_ptr), m_references(rhs.m_references) { }
// assignment
this_type & operator = (const this_type & rhs)
{
if (m_references.Reattach(rhs.m_references))
delete m_ptr;
m_ptr = rhs.m_ptr;
return *this;
}
~shared_lazy_ptr()
{
if (m_references.IsOnly())
delete m_ptr;
}
T & operator* () const
{
return *get();
}
T * operator-> () const
{
return get();
}
T * get() const
{
return m_ptr->get();
}
void reset(T * p)
{
if (p != get())
{
if (m_ptr != NULL)
delete m_ptr;
m_ptr = p;
}
}
// non-dereferencing accessors
T * peek() const
{
// may return NULL
return get()->peek();
}
bool dereferenced() const
{
return peek() != NULL;
}
// operator bool() const { return dereferenced(); }
// handle intrinsic conversion to testable bool using unspecified_bool technique
typedef T * this_type::*unspecified_bool_type;
operator unspecified_bool_type() const // never throws
{
return dereferenced() ? &this_type::m_ptr : NULL;
}
private:
lazy_ptr<T, F> * m_ptr; // shared *lazy* pointer to the actual object
ReferenceCount m_references; // shared reference count to our lazy pointer
};