Template parameters not used in partial specialization when usingtypedefined

J

jrwats

class Nil { };

template<class H, class T>
struct TypeList
{
typedef H Head;
typedef T Tail;
};

template
<class T01=Nil, class T02=Nil, class T03=Nil, class T04=Nil, class
T05=Nil,
//...
struct Seq;

template<class T01>
struct Seq<T01>
{
typedef TypeList<T01, Nil > Type;
};

template <typename R, class TList> class FunctorImpl;

// OK, finally the interesting bit. The below will error with:
// error: template parameters not used in partial specialization: ‘P1’
//
template <class R, class P1>
class FunctorImpl<R, typename Seq<P1>::Type >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

// This of course works:
//
template <class R, class P1>
class FunctorImpl<R, TypeList<P1, Nil> >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

// The motivation for this is I'd like to ultimate (instead of Seq)
// use the Function Signature specialization trick:

template <class Fun> struct Cons;

template <class T1> struct Cons<void (*)(T1)>
{
typedef TypeList<T1, Nil> Type;
};

template <class T1, class T2>
struct Cons<void (*)(T1, T2)>
{
typedef TypeList<T1, TypeList<T2, Nil> > Type;
};

//...

#define MakeTL(...) Cons< void (*) (__VA_ARGS__) >::Type

template <class R, class P1>
class FunctorImpl<R, typename MakeTL(P1) >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

But this fails for the same reason "class FunctorImpl<R, typename
Seq<P1>::Type >" fails.

Is there any way around this? This seems like it should be valid C+
+... but this appears to be compiler independent.
 
A

Alf P. Steinbach

* jrwats:
class Nil { };

template<class H, class T>
struct TypeList
{
typedef H Head;
typedef T Tail;
};

template
<class T01=Nil, class T02=Nil, class T03=Nil, class T04=Nil, class
T05=Nil,
//...
struct Seq;

template<class T01>
struct Seq<T01>
{
typedef TypeList<T01, Nil > Type;
};

template <typename R, class TList> class FunctorImpl;

// OK, finally the interesting bit. The below will error with:
// error: template parameters not used in partial specialization: ‘P1’
//
template <class R, class P1>
class FunctorImpl<R, typename Seq<P1>::Type >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

I think this is similar to how such an indirect (dependent) type cannot be
deduced for a function argument. The compiler's problem is, given some use of
FunctorImpl<X,Y>, find out if it matches the above with R=X and P1 some unique
type such that Seq<P1>::Type = Y. Uhm, deducing P1 from Y is rather difficult...

I guess you're thinking from the perspective of sort of handing in P1 and get
out Seq<P1>::Type.

The compiler, however, must work in the opposite direction: for any concrete use
of FunctorImpl it's handed some type Y, which it (if it accepted the code above)
would have to match against all possible Type in Seq<P1>::Type for all possible
P1, to find the presumably unique type P1.

// This of course works:
//
template <class R, class P1>
class FunctorImpl<R, TypeList<P1, Nil> >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

Yes. Given use of FunctorImpl<X, Y>, the compiler matches X to R, and Y to
that is said:
// The motivation for this is I'd like to ultimate (instead of Seq)
// use the Function Signature specialization trick:

template <class Fun> struct Cons;

template <class T1> struct Cons<void (*)(T1)>
{
typedef TypeList<T1, Nil> Type;
};

template <class T1, class T2>
struct Cons<void (*)(T1, T2)>
{
typedef TypeList<T1, TypeList<T2, Nil> > Type;
};

//...

#define MakeTL(...) Cons< void (*) (__VA_ARGS__) >::Type

template <class R, class P1>
class FunctorImpl<R, typename MakeTL(P1) >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

But this fails for the same reason "class FunctorImpl<R, typename
Seq<P1>::Type >" fails.

Is there any way around this? This seems like it should be valid C+
+... but this appears to be compiler independent.

Uhm, I think macros... ;-)


Cheers & hth.,

- Alf
 
J

jrwats

I think this is similar to how such an indirect (dependent) type cannot be
deduced for a function argument. The compiler's problem is, given some use of
FunctorImpl<X,Y>, find out if it matches the above with R=X and P1 some unique
type such that Seq<P1>::Type = Y. Uhm, deducing P1 from Y is rather difficult...

I guess you're thinking from the perspective of sort of handing in P1 and get
out Seq<P1>::Type.

The compiler, however, must work in the opposite direction: for any concrete use
of FunctorImpl it's handed some type Y, which it (if it accepted the code above)


Yes. Given use of FunctorImpl<X, Y>, the compiler matches X to R, and Y to
TypeList<P1, Nil>, that is, Y must be a type of that form, from which P1 follows.

Ahh... wasn't thinking about what the compiler had to do... this makes
sense.
Uhm, I think macros... ;-)

Yeah... That's how the Loki library (haven't looked at what Boost
does) does it. It defines a bunch of macros for typelists, but also
just specializes FunctorImpl on Seq itself:

template <class R, class P1>
class FunctorImpl<R, Seq<P1> >
{
public:
typedef R ResultType;
typedef P1 Parm1;
virtual R operator()(Parm1) = 0;
};

You can't pass in a TypeList to FunctorImpl (in this specialization)
but you potentially have access to a TypeList (in FunctorImpl's code)
via Seq::Type.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top