Check if an alias is a template in D 2.0

How to check if an alias is a template in D 2.0?

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

Update:

It should work as follows:

 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, what doesn't work:

  • You cannot use any expression, for example T!(...) , because you do not know what to put instead of ellipses.

  • You cannot say &T , because it also does not work if you simply have the simple name of the old type.

+6
templates d d2
source share
4 answers

This passes everything except 2 tests, which I listed in another 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 } 

Two tests that failed:

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

If you are sure that the template will not contain a default argument containing "...!(..." , I think it is safe to use.

+5
source share
 template isTemplate(alias T, Args...) { enum bool isTemplate = __traits(compiles, T!(Args)); } 

this also adds an additional restriction - it must be a template that can be created using the given arguments.

+1
source share

This code applies the operator address - '&' which is not applicable to patterns, for identification of the identifier of a pattern.

 struct S (T) { int a; int foo () () {} int xyz (A) (A a) {} void bar (T t) {} } void main () { S!(int) s; foreach (m; __traits(allMembers, S!(int))) writeln (m, " is template: ", !__traits(compiles, mixin("&s." ~ m))); } 

:

 a is template: false foo is template: true xyz is template: true bar is template: false 
+1
source share

A template alias parameter can take many things: variables, user types, modules, templates, and literals.

So, isTemplate should pass the following test cases:

 struct FooS(T) { struct Inner {} struct Inner2(string U="!(") {} int func(U)() { return 0; } int bar; } FooS!int foo; class FooC { int x; } union FooU { int x;} enum FooE { x } interface FooI { int x(); } template FooT(T) { struct Inner {} struct Inner2(string U="!(") {} int func(U)() { return 0; } int bar; } static assert(! isTemplate!0 ); static assert(! isTemplate!"0" ); static assert(! isTemplate!0.0f ); static assert(! isTemplate!'0' ); static assert(! isTemplate!'!' ); static assert(! isTemplate!"module std.stdio" ); static assert(! isTemplate!null ); static assert(! isTemplate!true ); static assert(! isTemplate!__FILE__ ); static assert(! isTemplate!__LINE__ ); static assert(! isTemplate!([]) ); static assert( isTemplate!FooS ); static assert(! isTemplate!(FooS!int) ); static assert( isTemplate!(FooS!int.func) ); static assert(! isTemplate!(FooS!int.func!float) ); static assert(! isTemplate!(FooS!int.bar) ); static assert(! isTemplate!(FooS!int.Inner) ); static assert( isTemplate!(FooS!int.Inner2) ); static assert(! isTemplate!(FooS!int.Inner2!"?") ); static assert( isTemplate!FooT ); static assert(! isTemplate!(FooT!int) ); static assert( isTemplate!(FooT!int.func) ); static assert(! isTemplate!(FooT!int.func!float) ); static assert(! isTemplate!(FooT!int.bar) ); static assert(! isTemplate!(FooT!int.Inner) ); static assert( isTemplate!(FooT!int.Inner2) ); static assert(! isTemplate!(FooT!int.Inner2!"?") ); static assert(! isTemplate!foo ); static assert( isTemplate!(foo.func) ); static assert( isTemplate!isTemplate ); static assert(! isTemplate!(isTemplate!isTemplate) ); static assert(! isTemplate!FooC ); static assert(! isTemplate!FooU ); static assert(! isTemplate!FooE ); static assert(! isTemplate!FooI ); static assert(! isTemplate!((int x){return x;}) ); static assert( isTemplate!(std.stdio.writefln) ); static assert(! isTemplate!(std.stdio) ); static assert(! isTemplate!std ); 
+1
source share

All Articles