There is a bug with the calls to DoGetPrototype and DoSetPrototype. I've rewritten the class to fix that bug and make some small improvements.
////////////////////////////////////////////////////////////////////////////////
// class template PrototypeFactoryUnit
// Creates an object by cloning a prototype
// GetPrototype takes a reference to pointer instead of returning the pointer by
// value.
// GetPrototype and SetPrototype use the helper friend function templates
// DoGetPrototype and DoSetPrototype. The friend function templates are passed
// a possibly up-casted reference.
////////////////////////////////////////////////////////////////////////////////
template <class, class>
class PrototypeFactoryUnit;
namespace Private
{
template <class CP, class Base>
inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
typename Base::ProductList::Head* & pPrototype)
{
pPrototype = me.pPrototype_;
}
template <class CP, class Base>
inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
typename Base::ProductList::Head* pPrototype)
{
me.pPrototype_ = pPrototype ;
}
}
template <class /*ConcreteProduct*/, class Base>
class PrototypeFactoryUnit : public Base
{
typedef typename Base::ProductList BaseProductList;
typedef typename BaseProductList::Head AbstractProduct;
protected:
typedef typename BaseProductList::Tail ProductList;
PrototypeFactoryUnit() : pPrototype_(0)
{}
template <class CP, class Base1>
friend void Private::DoGetPrototype
(const PrototypeFactoryUnit<CP, Base1>&,
typename Base1::ProductList::Head* &);
template <class CP, class Base1>
friend void Private::DoSetPrototype
(PrototypeFactoryUnit<CP, Base1>&,
typename Base1::ProductList::Head*);
public:
template <class U>
void GetPrototype(U * &pPrototype) {
Private::DoGetPrototype<U>(*this, pPrototype);
}
template <class U>
void SetPrototype(U *pPrototype) {
Private::DoSetPrototype<U>(*this, pPrototype);
}
private:
AbstractProduct* DoCreate(Type2Type<AbstractProduct>)
{
assert(pPrototype_);
return pPrototype_->Clone();
}
AbstractProduct* pPrototype_;
};