views:

224

answers:

2

(from reading chapter 3 of modern c++ design)

typelist.hpp:

class NullType {};

struct EmptyType {};


template <class T, class U>
struct Typelist
{
  typedef T Head;
  typedef U Tail;
};

#define TYPELIST_1(T1) Typelist<T1, NullType>
#define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2) >
#define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3) >
#define TYPELIST_4(T1, T2, T3, T4) Typelist<T1, TYPELIST_3(T2, T3, T4) >
#define TYPELIST_5(T1, T2, T3, T4, T5) Typelist<T1, TYPELIST_4(T2, T3, T4, T5) >
#define TYPELIST_6(T1, T2, T3, T4, T5, T6) Typelist<T1, TYPELIST_5(T2, T3, T4, T5, T6) >


namespace TL
{
  template <class TList> struct Length;
  template <> struct Length<NullType>
  {
    enum { value = 0 };
  };

  template <class T, class U>
    struct Length< Typelist<T, U> >
    {
      enum { value = 1 + Length<U>::value };
    };


  template <class Head, class Tail>
    struct TypeAt<Typelist<Head, Tail>, 0>
    {
      typedef Head Result;
    };

  template <class Head, class Tail, unsigned int i>
    struct TypeAt<Typelist<Head, Tail>, i>
    {
      typedef typename TypeAt<Tail, i-1>::Result Result;
    };

}

main.cpp

#include "typelist.hpp"

Typelist<int, double> foo;

int main() {
}

g++ main.cpp typelist.hpp:37: error: ‘TypeAt’ is not a template typelist.hpp:43: error: type/value mismatch at argument 2 in template parameter list for ‘template struct TL::TypeAt’ typelist.hpp:43: error: expected a type, got ‘i’

Why do I get this error? How do I fix this?

+1  A: 

Typelist is designed to be used recursively: It expects its second templater parameter to be either another Typelist, or NullType (signaling the end of recursion).

To define foo, you should write:

TYPELIST_2(int, double) foo;

or, if you want to avoid macros:

Typelist<int, Typelist<double, NullType> > foo;
Éric Malenfant
This isn't the problem, nor a problem.
GMan
@GMan: Re-reading the compiler error reported in the question, I agree that this is not *the* problem. However, it is *a* problem: TL::Lenght or TL::TypeAt can't be used on a Typelist as defined in the question.
Éric Malenfant
@Eric: You are very right about it being a problem, my mistake. :)
GMan
+3  A: 

Looks like you're missing a forward declaration.

This is a partial specialization:

template <class Head, class Tail>
struct TypeAt<Typelist<Head, Tail>, 0>

But the compiler has no idea what it's a specialization of. Add this before it:

template <class List, unsigned Index>
struct TypeAt;

This let's the compiler know: "There is a class TypeAt which has two template parameters." So now when you specialize it, the compiler knows what class you're talking about.


Note, your usage of Typelist is incorrect. These algorithm's are sentinel-terminated. This means, like C-strings, they expect the data to be concluded with a special value. In our case, this is NullType.

So, take Éric's advice. (i.e. hint: if you found his answer helpful, up-vote it.)

GMan
+1: 30 seconds too late
John Dibling