Search code examples
templatesd

Test if an Alias is a Template in D 2.0


How do I test if an alias is a template in D 2.0?

template isTemplate(alias T)
{
    enum bool isTemplate = ???;
}

Update:

It should work like:

struct S(T)
{
    int opCall() { return 0; }
    int opUnary(string s)() if (s == "-") { return 0; }
}

pragma(msg, isTemplate!(S));                 //Should print true
pragma(msg, isTemplate!(S!(int)));           //Should print false
pragma(msg, isTemplate!((S!(int)).opCall));  //Should print false
pragma(msg, isTemplate!((S!(int)).opUnary)); //Should print true

For reference, things that don't work:

  • You can't use any expression like T!(...) because you don't know what to put in place of the ellipses.

  • You can't say &T because that also doesn't work if you're just given a plain old type name.


Solution

  • This passes all except 2 tests I have listed in the other answer

    import std.algorithm : startsWith, canFind;
    
    template isTemplate(alias B) {
        enum isTemplate = !__traits(compiles, {auto x=B;})      // excludes values
                       && !__traits(compiles, {B x;})           // excludes types
                       && __traits(compiles, {alias B x;})      // excludes instance members
                       && !B.stringof.startsWith("module ", "package ") // excludes modules
                       && !B.stringof.canFind("!(");             // excludes instantiated templates
    }
    

    The 2 tests that have failed like:

    struct Inner2(string U="!(") {}
    static assert(isTemplate(Inner2));
    

    If you are sure the template won't have a default argument containing "...!(..." I think it is safe to use.