Template parameters not used in partial specialization when usingtypedefined

Discussion in 'C++' started by jrwats, Jul 11, 2009.

  1. jrwats

    jrwats Guest

    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.
    jrwats, Jul 11, 2009
    #1
    1. Advertising

  2. * 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
    TypeList<P1, Nil>, that is, Y must be a type of that form, from which P1 follows.


    >
    > // 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
    Alf P. Steinbach, Jul 11, 2009
    #2
    1. Advertising

  3. jrwats

    jrwats Guest

    On Jul 11, 12:34 pm, "Alf P. Steinbach" <> wrote:
    >
    > 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
    > 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.
    jrwats, Jul 11, 2009
    #3
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. case2005
    Replies:
    3
    Views:
    1,789
    Nicolas Pavlidis
    Feb 13, 2005
  2. toton
    Replies:
    1
    Views:
    607
  3. vj
    Replies:
    1
    Views:
    473
  4. Hizo
    Replies:
    17
    Views:
    667
    itaj sherman
    Mar 7, 2011
  5. Markus
    Replies:
    2
    Views:
    306
    88888 Dihedral
    Dec 11, 2011
Loading...

Share This Page