www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Static map

The problem is to create a generic construct that would allow to map
types, literals and other statically available stuff to other types,
aliases, etc. I'm sure, Andrei knows a scientific term for it but I'll
further abuse 'static' and name the construct StaticMap. My first
naive attempt was to use regular mixins:

/**
    Enables aliasing of expressions.
*/
template Alias(A...) if (A.length = 1)
{
    static if (__traits(compiles, { alias A[0] x; }))
        alias A[0] Alias;
    else
        enum Alias = A[0];
}


template StaticMap(A...)
{
    template Parse(B...)
    {
        static if (B.length)
        {
            static assert (B.length > 1, "No value for key " ~ B[0] ~
" in " ~ A.stringof);

            static if (is(B[0]))
            {
                template Get(Key) if (is(Key == B[0]))
                {
                    alias Alias!(B[1]) Get;
                }
            }
            else static if  (__traits(compiles, { static if(B[0] ==
B[0]) {} }))
            {
                template Get(alias key) if ( B[0] == key )
                {
                    alias Alias!(B[1]) Get;
                }
            }
            else
            {
                template Get(alias key) if ( __traits(isSame, key,
B[0]) )
                {
                    alias Alias!(B[1]) Get;
                }
            }

            mixin Parse!(B[2..$]);
        }

    }

    mixin Parse!(A);
}

alias StaticMap!(
    int,               "type",
    2,                 "two",
    StaticMap,    int
    ) map;

static assert(map.Get!(int) == "type");
static assert(map.Get!(2) == "two");
static assert(is(map.Get!(StaticMap) == int));
----

But the above doesn't work because the template overloads get mixed in
their own scopes and only the outmost is matched. With functions, one
can alias the overload into the surrounding scope by using a named
mixin like this:

template Foo()
{
    void foo(int x) {} ;
}

void foo() {};
mixin Foo a;
alias a.foo foo;
// now foo(int) from the mixin overloads foo();

But one can't do the same with overloaded templates. So there are two
questions:

1. Is it a bug, unimplemented feature or by design?
2. Is there a way to implement the construct without falling back to
string mixins?
Nov 12 2008