template<
typename T>
class bio::LazyPointer< T >
LazyPointer<T> is an owning smart pointer that defers the allocation of its T until the first access through operator-> or operator* (or an explicit Get()). Two construction modes:
- Eager: pass a T* directly. The pointer is stored as-is; no factory is involved. Behaves like a unique_ptr — operator-> just returns the stored pointer, never allocates.
- Lazy: pass a Factory (function pointer returning a T*). The stored pointer starts NULL; the first dereference invokes the factory and caches the result. Subsequent accesses return the cached pointer. The dtor delete[s] whatever the factory produced.
The dtor only delete[s] if the pointer was actually materialised, so a lazy LazyPointer that was never dereferenced costs nothing at destruction.
Two explicit peek/control accessors exist to deliberately NOT materialise:
And two write-side controls:
- SetFactory(Factory) swaps the factory; never materialises
- ResetWith(T*) replaces the cached pointer (delete[s] the previous one if any). Useful when a derived class wants to populate the slot itself (e.g. Atom::Spin replacing a default Symmetry with a chemical::Symmetry).
- Release() transfers ownership out without delete'ing.
Copy semantics: factory propagates, materialised pointer does NOT. This matches the existing Wave copy-ctor contract for mSymmetry — a clone gets a fresh empty cache and re-materialises on demand.
NOT THREAD SAFE. Wave's mSymmetry is documented as a per-instance cache and existing Wave methods aren't thread-safe either, so we keep the same guarantees.
Design note: T may be forward-declared at the LazyPointer<T> declaration site, but the destructor's delete mPtr requires the full type at the point where ~LazyPointer<T> is implicitly instantiated (typically in the .cpp that defines the owning class's dtor). This is the same constraint std::unique_ptr<T> imposes; obey it the same way.