digitalmars.D.learn - Determining if a class has a template function
- Straivers (15/15) Oct 11 2016 I have a class T with a templated function foo(string name)(int,
- Basile B. (25/40) Oct 12 2016 For this particular example the following solution works:
- Meta (16/60) Oct 12 2016 There is also isTemplate
- Meta (3/13) Oct 12 2016 Whoops, I forget to say that fstr is defined like this:
- Marc =?UTF-8?B?U2Now7x0eg==?= (6/17) Oct 14 2016 This won't work if there are additional parens _inside_
- Meta (5/23) Oct 14 2016 You're right... And this is why it's such an ugly hack. It can
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); }
Oct 11 2016
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"
Oct 12 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: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);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"
Oct 12 2016
On Wednesday, 12 October 2016 at 16:57:50 UTC, Meta wrote://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);Whoops, I forget to say that fstr is defined like this: enum fstr = f.stringof;
Oct 12 2016
On Wednesday, 12 October 2016 at 16:57:50 UTC, Meta wrote: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);This won't work if there are additional parens _inside_ compile/runtime parameters, though, which there is ample opportunity for: T func(T : U!(int, string), U)(const(T) param = defaultValue!(const(T))());
Oct 14 2016
On Friday, 14 October 2016 at 09:15:40 UTC, Marc Schütz wrote:On Wednesday, 12 October 2016 at 16:57:50 UTC, Meta wrote:You're right... And this is why it's such an ugly hack. It can probably be improved upon but I would not recommend trying, although there's no other way I can think of to determine whether a template is a function template.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);This won't work if there are additional parens _inside_ compile/runtime parameters, though, which there is ample opportunity for: T func(T : U!(int, string), U)(const(T) param = defaultValue!(const(T))());
Oct 14 2016