Thread overview |
---|
October 11, 2016 Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
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); } |
October 12, 2016 Re: Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Straivers | 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"
|
October 12, 2016 Re: Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | 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); |
October 12, 2016 Re: Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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;
|
October 14, 2016 Re: Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | 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))());
|
October 14, 2016 Re: Determining if a class has a template function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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:
>> 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))());
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.
|
Copyright © 1999-2021 by the D Language Foundation