Thread overview
Suggestion : improve compile-time type manipulation facilities
Jun 29, 2004
Alex B.
Jun 29, 2004
Andy Friesen
Jun 29, 2004
Alex B.
Jun 29, 2004
Andy Friesen
Jun 29, 2004
Sean Kelly
June 29, 2004
It seems pattern matching in specialization facilities of D aren't powerful enough to implement concept of type-lists. Well it simply can't match smthing like 'template <class T, class U> struct Length< Typelist<T, U> >' and it is essential feature of C++ template engine.

I tried a simpler way to implement them and discovered a serious clash between 'properties' concept and type aliasing.

Here is the code:

class NullType
{
}

template TypeList(U,V)
{
class TypeList
{
alias U Head;
alias V Tail;
}
}


template TL_Length(Arg : NullType)
{
enum
{
Result = 0
}
}


template TL_Length(Arg)
{
enum
{
Result = 1 + TL_Length!(Arg.Tail).Result
}
}

void main()
{
// no property 'Tail' for type 'TypeList'
printf("%d\n",TL_Length!(TypeList!(int,TypeList!(float,NullType))).Result);
// ok
typeid(TypeList!(int,TypeList!(float,NullType)).Tail).print();
// no property 'Tail' for type 'TypeList'
typeid(TypeList!(int,TypeList!(float,NullType)).Tail.Tail).print();
// .property not implemented for typeof
typeid(typeof(TypeList!(int,TypeList!(float,NullType)).Tail).Tail).print();
}

Are there any work-arounds? Is it possible to make a proper implementation of specialization?


June 29, 2004
Alex B. wrote:
> It seems pattern matching in specialization facilities of D aren't powerful
> enough to implement concept of type-lists. Well it simply can't match smthing
> like 'template <class T, class U> struct Length< Typelist<T, U> >' and it is
> essential feature of C++ template engine.
> 
> I tried a simpler way to implement them and discovered a serious clash between
> 'properties' concept and type aliasing.
> 
> Here is the code:
> 
> class NullType
> {
> }
> 
> template TypeList(U,V)
> {
> class TypeList
> {
> alias U Head;
> alias V Tail;
> }
> }
> 
> 
> template TL_Length(Arg : NullType)
> {
> enum
> {
> Result = 0
> }	
> }
> 
> 
> template TL_Length(Arg)
> {
> enum
> {
> Result = 1 + TL_Length!(Arg.Tail).Result
> }
> }
> 
> void main()
> {
> // no property 'Tail' for type 'TypeList'
> printf("%d\n",TL_Length!(TypeList!(int,TypeList!(float,NullType))).Result);
> // ok typeid(TypeList!(int,TypeList!(float,NullType)).Tail).print();
> // no property 'Tail' for type 'TypeList'  typeid(TypeList!(int,TypeList!(float,NullType)).Tail.Tail).print();
> // .property not implemented for typeof
> typeid(typeof(TypeList!(int,TypeList!(float,NullType)).Tail).Tail).print();
> }
> 
> Are there any work-arounds? Is it possible to make a proper implementation of
> specialization?

I believe this is a bug.  One workaround is to do:

    struct Empty{}

    template TypeList(_Head, _Tail) {
        struct TypeList {
            alias _Head HeadType;
            alias _Tail TailType;

            HeadType head;
            TailType tail;
        }
    }

    template Length(_TL) {
        // _Tl.HeadType or TailType won't work.  But this will:
        const int Length = 1 + .Length!(typeof(_TL.tail));
    }

    template Length(_TL : Empty) {
        const int Length = 0;
    }

 -- andy
June 29, 2004
Attempting to compile this example in version 0.93 actually crashes the compiler.  And it produces different errors as well.  So I would report this as a bug in 0.93 and see how things work once it's been fixed.


Sean


June 29, 2004
>I believe this is a bug.  One workaround is to do:

Thanks! Excellent code.

D's ability to directly return value of template instaniation is totally cool. Too bad it doesn't support specialization well enough. :(


June 29, 2004
Alex B. wrote:

>>I believe this is a bug.  One workaround is to do:
> 
> 
> Thanks! Excellent code.
> 
> D's ability to directly return value of template instaniation is totally cool.
> Too bad it doesn't support specialization well enough. :(

The problem is that, somehow, aliases aren't quite first class citizens of the namespace.  Like I said, I believe this to be a bug, not a deficiency. :)

I really would like to see some more clever deduction, though, a la:

template LastTwo(_Head, _Dummy : TypeList!(_TailHead, _TailTail : Empty)) {
    alias _TailHead Last;
    alias _Head SecondLast;
}

 -- andy