Determining if a class has a template function

Meta via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Oct 12 09:57:50 PDT 2016


On Wednesday, 12 October 2016 at 16:29:22 UTC, Basile B. wrote:
> On Tuesday, 11 October 2016 at 20:17:19 UTC, Straivers wrote:
>> I have a class T with a templated function foo(string 
>> name)(int, int, float) that will be mixed in via template, and 
>> I want to determine if that class has mixed it in such that 
>> foo(name = "bar"). How could I go about this? Thanks.
>>
>> eg:
>>
>> mixin template A(string name, Args...) {
>>     void foo(string fooName)(Args args)
>>         if (fooName == name) {}
>> }
>>
>> template hasFoo(string name, A) {
>>     enum hasFoo = ???
>> }
>>
>> class B {
>>     mixin A!("mash", int, int, string);
>> }
>
> For this particular example the following solution works:
>
> template A(string name, Args...)
> {
>     void foo(string fooName)(Args args)
>         if (fooName == name) {}
> }
>
> template hasFoo(string name, T, V...)
> {
>     enum hasFoo = __traits(hasMember, T, "foo") &&
>         is(typeof(T.foo!name) == typeof(A!(name,V).foo!name));
> }
>
> class B
> {
>     mixin A!("mash", int, int, string);
> }
>
> unittest
> {
>     static assert( hasFoo!("mash", B, int, int , string));
>     static assert( !hasFoo!("rash", B, int, uint , string));
> }
>
>
> Now I can't say that I's generic enough to validate any members 
> that's injected.
> Note well that it wouldn't work with a regular mixin template.
>
> You can also take a look at "std.traits.TemplateOf"

There is also isTemplate 
(https://dlang.org/spec/traits.html#isTemplate). You can check 
first that the member exists and then check if it's a template 
(though this will pick up more than just template functions). 
There's also a *very* ugly hack you can do:

//A template function's .stringof is of the format <function 
name>(<template args>)(<function args>)
//so match on the number of brackets to determine whether it's a 
template function or not
enum isTemplateFunction = __traits(isTemplate, f)
                               && fstr.balancedParens('(', ')')
                               && (fstr.canFind("if")
                                   || fstr.count!(c =>
                                          cast(bool)c.among!('(', 
')')) == 4);


More information about the Digitalmars-d-learn mailing list