Few days ago I described a mechanism which allows bind–like operations for constructors. In other words it gives opportunity for us to define object construction details once (e.g. all parameters required for object construction) and later to create this object, but without the need to specify these parameters at the place of creation, i.e. we first bind constructor’s parameters to some helper object and later we just ask this helper object to create our original object, whilst the helper cares about all construction parameters for our obj.
I decided to develop this idea a bit further to allow “multi–level” delayed construction of objects.
In other words to allow delayed construction of objects that by themselves parameters for other objects being delayed–constructed. This would allow one to create a chain of such delayed–constructed objects. Until main (root) object is requested to be constructed — the rest of objects, upon which the root one is dependent, will also remain unconstructed. But as soon as root obj is created — all the others will be created in a chain, in a depth–first manner.
The actual implementation idea behind that functionality is very simple: we’ll just add a type cast operator for our DelayedConstructor helper. This type cast operation will actually create the embedded object. Having this we can pass instances of DelayedConstructor in place of actual objects. When this would happen all appropriate objects will be created and passed as required.
By the way, all these things are done in a static manner, without using procedural code from the interface perspective — we just say “prepare to create Obj with parameters Args… when we ask you to”. — all in a single line.
Besides that I added creation policies for the objects being created, so we can use new, copy or move–like construction:
template <class T>
struct CreateNew
{
typedef T* TCreated;
template <class ...Args>
TCreated Create(Args ...args)
{
return new T(args...);
}
};
template <class T>
struct CreateCopy
{
public:
typedef T TCreated;
template <class ...Args>
TCreated Create(Args ...args)
{
return TCreated(args...);
}
};
template <class T>
struct CreateMove
{
public:
typedef T&& TCreated;
template <class ...Args>
TCreated Create(Args ...args)
{
return T(args...);
}
};
These are self–explanatory and don’t require much attention I believe.
Instead, let’s have a look at our modified DelayedConstructor: it has just an added creation policy handing in its inner worker class plus adds an appropriate type cast operator.
template <class TObject, template <class T> class TCreationPolicy = CreateNew>
class DelayedConstructor
{
public:
typedef typename TCreationPolicy<TObject>::TCreated TCreated;
template <class ...Args>
DelayedConstructor(Args ...args)
{
class ConstructHelper
{
public:
static TCreated DoConstruct(Args ...args)
{
return TCreationPolicy<TObject>().Create(args...);
}
};
m_funHelper = boost::bind(ConstructHelper::DoConstruct, args...);
}
TCreated operator()()
{
return m_funHelper();
}
operator TCreated()
{
operator()();
}
protected:
boost::function<TCreated(void)> m_funHelper;
};
That’s pretty all.
Now we can happily do things like that:
//Creation via operator new DelayedConstructor<int> dc(42); int *pInt = dc(); //Creation via returning a copy from inner stack int vInt = DelayedConstructor<int, CreateCopy>(42); //2--level delayed construction: //First we create an int on stack via copying and the //we create an std::string via new //Int argument is created only _after_ //std::string has been requested to create an instance delayedConstructor<std::string> strDc = DelayedConstructor<std::string>(DelayedConstructor<int, CreateCopy>(42)); std::string str = strDc();



