Question

(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<class Head, class Tail> struct TL::TypeAt’
typelist.hpp:43: error:   expected a type, got ‘i’

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

Was it helpful?

Solution

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.)

OTHER TIPS

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top