Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A struct inherits itself

Tags:

c++

templates

I got a piece of code from my friend. But I am really confused, how can a struct inherit from itself? Does the inheritance make much sense?

template<class TYPELIST>
struct Field : public Field<typename TYPELIST::Tail> {
  typedef TYPELIST TypeListType;
  typename TypeListType::Head item_;
};

template<>
struct Field<TypeListEnd> {
};

I don't know what's going on here.

like image 534
whileone Avatar asked Jun 25 '12 01:06

whileone


1 Answers

Field doesn't inherit from itself; rather, template<typename TYPELIST> Field inherits from Field<typename TYPELIST::Tail>. It's fine as long as the two lists of template arguments are distinct.

Typelists were an archaic method of allowing templates to (in effect) take a variable number of type arguments, before variadic templates were added to the language. They implemented a simple singly linked list structure, equivalent to LISP cons cells, where Head was the "payload" type and Tail the remainder of the list, which would either be a typelist or a TypeListEnd type, equivalent to LISP nil.

Suppose we have

typename TypeList<int, TypeList<char, TypeList<float, TypeListEnd> > > MyTypeList;

Here I'm assuming that TypeList is a template defining Head and Tail typedef members corresponding to its first and second template parameters respectively:

template<typename Head, Tail> struct TypeList { typedef Head Head; typedef Tail Tail; };

Note that I'm having to space-separate the closing angle brackets, as this might have to be compiled on a C++03 compiler, where >> is always even in template context interpreted as the right-shift operator.

Then your Field metafunction, when invoked on MyTypeList, will expand into

Field<MyTypeList>;

Field<typename TypeList<int, TypeList<char, TypeList<float, TypeListEnd> > > >;

struct Field<...>: TypeList<int, TypeList<char, TypeList<float, TypeListEnd> > >::Tail {
    TypeList<int, TypeList<char, TypeList<float, TypeListEnd> > >::Head item;
};

struct Field<...>: TypeList<char, TypeList<float, TypeListEnd> > {
    int item;
};

...

struct Field<...>: struct Field<...>: struct Field<...>: struct Field<TypeListEnd> {
} {
    float item;
} {
    char item;
} {
    int item;
};

This provides you with a struct containing by public inheritance all of the types in your typelist. Of course, doing anything useful with such a struct is another matter and is left as an exercise for the reader.

like image 179
ecatmur Avatar answered Nov 14 '22 22:11

ecatmur