To expalin hos it works let me simplify the code:
Code:
#include <list>
using namespace std;
template <class R>
class Item {
public:
typedef typename R::I_handle handle;
void SetHandle(handle h) {a=h;}
handle GetHandle() {return a;}
private:
handle a;
};
template < template < class > class I = Item >
class Container {
public:
typedef Container<I> Self;
typedef typename I<Self> Item;
typedef list<Item> Item_list;
typedef typename Item_list::iterator I_handle;
Item_list items;
};
int main()
{
Container<> a;
Container<>::Item i;
Container<>::Item i1;
i.SetHandle(i1.GetHandle());
a.items.push_back(i);
}
So we get rid of Wrapper, but get a template as template param
The type dependencies contain a cycle; the item type need a template argument that tells it the handle type. The Container knows the handle type and can be used as the actual type for the template argument of the item type, even though the handles have not been defined at this point. However, it is the difference between declaration and definition that allows us to use the declared type of the Container for the item type instantiation.
With respect to this instantiation the idea of this code is simuliar to Curiously Recurring Template Pattern:
Code:
template <class T>
class Base
{
.......
};
class Curious:public Base<Curious>
{
........
};