#include <iostream>

class Fill{};

//====================================================================

class Node
{
public:
	Node(){}
	Node(Fill*) { }

	virtual ~Node() {}
	virtual Node * clone() const = 0;

	virtual void id() { std::cout << "Node\n"; }
};

//====================================================================

template <typename Base, typename Derived>
class NodeWrap : public Base
{
public:

	NodeWrap() { } 
	NodeWrap(Fill * arg1) : Base(arg1) { }

	virtual Node *clone() const
	{
		return new Derived(static_cast<Derived const &>(*this));
	}
};

//====================================================================

template <typename Base, typename Derived>
class NodeWrapVirtual : public virtual Base
{
public:

	NodeWrapVirtual() { }
	NodeWrapVirtual(Fill * arg1) : Base(arg1) { }

	virtual Node *clone() const
	{
		return new Derived(static_cast<Derived const &>(*this));
	}
};

//====================================================================

class NodeA : public NodeWrap<Node, NodeA>
{
public:
	typedef NodeWrap<Node, NodeA> BaseClass;

	NodeA() { }
	NodeA(Fill * f) : BaseClass(f) { }

	virtual void id() { std::cout << "NodeA\n"; }

}; 

//====================================================================

class NodeB : public NodeWrapVirtual<Node, NodeB>
{
public:
	typedef NodeWrapVirtual<Node, NodeB> BaseClass;

	NodeB() { }
	NodeB(Fill * f) : BaseClass(f) { }
	
	virtual void id() { std::cout << "NodeB\n"; }
};

//====================================================================

class NodeC : public NodeWrapVirtual<Node, NodeC>
{
public:
	typedef NodeWrapVirtual<Node, NodeC> BaseClass;

	using BaseClass::clone;

	NodeC() { }
	NodeC(Fill * f) : BaseClass(f) { }

	virtual void id() { std::cout << "NodeC\n"; }
};

//====================================================================

class NodeD : public NodeWrap<NodeB, NodeD>,
							public NodeWrap<NodeC, NodeD>
{
public:

	typedef NodeWrap<NodeB, NodeD>	BaseClassB;
	typedef NodeWrap<NodeC, NodeD>	BaseClassC;

	NodeD() { }
	NodeD(Fill * f) : BaseClassB(f), BaseClassC(f) { }

	//using BaseClassB::clone;  // (1)
	virtual NodeD *clone() const { return new NodeD(*this); }		// (2)

	virtual void id() { std::cout << "NodeD\n"; }
};

int main()
{
	Node * a = new NodeA;
	Node * b = new NodeB;
	Node * c = new NodeC;
	Node * d = new NodeD;

	a->id();
	b->id();
	c->id();
	d->id();

	Node * clone = a->clone();
	clone->id();
	clone = b->clone();
	clone->id();
	clone = c->clone();
	clone->id();
	clone = d->clone();
	clone->id();
}