It should in theory help defer to the last minute the computation of whatever state you want... (nots supposed to multithread yet)
template<typename T>
struct LazyState
{
using value_type = T;
// Default constructor: initialize with default values.
inline LazyState()
: mUpdateCb(nullptr), mbUpdated(false) {}
// Constructor with an initial state.
inline explicit LazyState(const T& initialState)
: mState(initialState), mUpdateCb(nullptr), mbUpdated(false) {}
// Constructor with an initial state and an update callback.
inline LazyState(const T& initialState, std::function<bool(T&)> updateCallback)
: mState(initialState), mUpdateCb(updateCallback), mbUpdated(false) {}
// Constructor with an update callback only.
inline explicit LazyState(std::function<bool(T&)> updateCallback)
: mUpdateCb(updateCallback), mbUpdated(false) {}
inline void MarkOutdated()
{
mbUpdated = false;
}
inline T& Access(bool bUpdateIfNeeded = true)
{
if (bUpdateIfNeeded && !mbUpdated && mUpdateCb)
mbUpdated = mUpdateCb(mState);
return mState;
}
inline T& operator*()
{
T& state = Access(true);
if (mbUpdated)
return state;
throw std::exception("Fail State Update");
}
std::function<bool(T&)> mUpdateCb;
std::atomic<bool> mbUpdated;
private:
T mState;
};