July 31, 2004
Given:

    import std.stdio;

    template Test(T) {
        void Test() {
            writefln("Scalar: ", typeid(T).toString());
        }
    }

    template Test(ArrayType : ArrayType[]) {
        void Test() {
            writefln("Array: ", typeid(ArrayType).toString());
        }
    }

    template Test(ValueType, KeyType : KeyType[ValueType]) {
        void Test() {
            writefln("Associative array ",
                typeid(KeyType).toString(), " => ",
                typeid(ValueType).toString());
        }
    }

    int main() {
        Test!(int)();
        Test!(char[])();
        Test!(int, int[int])();
        return 0;
    }

The last template instantiation in main() fails because no match was found.

Renaming ValueType to either ArrayType or T causes the compile to succeed.

Even then, though, the match only succeeds if the first argument, and the key *and* value types of the second, are identical.  (eg Test!(real, real[real]) works, but Test!(int, char[int]) does not)

Sort of related but separate issue: Changing the second instantiation to Test!(float[][]) causes the link to fail. (no TypeInfo for float[], I assume)

Also sort of related:  It is legal to write

    template Foo(T : void delegate(T)) { ... }

However, as far as I can tell, the specialization is never selected.

 -- andy