Phobos has a number of non-function template traits (std.traits, std.typetuple etc), eg:

---- in std.traits:
template hasMember(T, string name) {
    static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
        enum bool hasMember =
            staticIndexOf!(name, __traits(allMembers, T)) != -1 ||
            __traits(compiles, { mixin("alias Identity!(T."~name~") Sym;"); });
    else
        enum bool hasMember = false;
}
----

I see those disadvantages with non-function templates:

* syntax is less clear than regular function templates (there's no way to tell the return type without looking at the code or using some convention relating to the template name)

* they're not DRY, as the template name is typically repeated (maybe in multiple places) inside the template body (hasMember appears 3 times here)

* behavior of templates is actually weird, for example:

----
template A1(T){enum A1=0;}
template A2(T){enum B=0;}
template A3(T){enum A3=0;enum B=0;}
void main(){
    enum a1=A1!int;    //ok
    enum a2=A2!int.B;    //ok
    //    enum a3=A3!int.B;    //Error: no property 'B' for type 'int'
}
----

Maybe this was for historical reasons (ie CTFE might've come after those design patterns were invented).

I would propose to use regular template functions instead, whenever possible (essentially for the ones that return a value):

For our example, this would become:
----
bool hasMember(T, string name)(){
    static if (is(T == struct) || is(T == class) || is(T == union) || is(T == interface))
        return staticIndexOf!(name, __traits(allMembers, T)) != -1 ||
                __traits(compiles, { mixin("alias Identity!(T."~name~") Sym;"); });
    else 
return false;
}
// can be used in exactly the same way:
static assert(hasMember!(A,"field"));
----

Advantages:
* clear syntax: returns bool, and body is simpler to read as well
* DRY: hasMember only mentioned once
* no weird behavior as above
doesn't break any code as usage is the same (backwards compatible)

In fact, I was able to convert with no problems a number of other such templates:
staticIndexOf
isSame
expectType
genericIndexOf
etc...

For the latter (genericIndexOf), the template body contained a clause like that:
enum next  = genericIndexOf!(e, tail).index;
enum index = (next == -1) ? -1 : 1 + next;
during conversion, I just had to add the line:
return Tuple!(int, "index",int, "next")(index,next);
which could further be simplified using a helper function as its a common idiom, into:
return TupleNamed!("index","next")(index,next);


Limitations
One typical case where this isn't possible is when a template defines an type alias, eg:
----
template Iota(int stop) {
    static if (stop <= 0)
        alias 
Iota=TypeTuple!();
    else
        alias 
Iota=TypeTuple!(Iota!(stop-1), stop-1);
}  
----