Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
June 30, 2018 template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
I have a template that I want to provide easy aliases for, where the aliases includes (partially applies?) a template parameter.
void fooImpl(char token, T)(const T line)
{
// ...
}
alias quoteFoo(T) = fooImpl!('"', T);
alias singlequoteFoo(T) = fooImpl!('\'', T);
void main()
{
quoteFoo(`"asdf"`);
singlequoteFoo(`'asdf'`);
}
...was how I'd imagined it would look.
>onlineapp.d(11): Error: template onlineapp.quoteFoo cannot deduce function from argument types !()(string), candidates are:
>onlineapp.d(6): onlineapp.quoteFoo(T)
If I manually pass string as a template parameter, like quoteFoo!string("bar") or singlequoteFoo!string("baz"), it works.
Can I do it this way or do I need to write wrapping functions?
|
June 30, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Anonymouse | On Saturday, 30 June 2018 at 21:11:54 UTC, Anonymouse wrote: > I have a template that I want to provide easy aliases for, where the aliases includes (partially applies?) a template parameter. > > > void fooImpl(char token, T)(const T line) > { > // ... > } > > alias quoteFoo(T) = fooImpl!('"', T); would be the same as template quoteFoo(T) { alias quoteFoo = fooImpl!('"', T); } There is no "Implicit Function Template Instantiation (IFTI)" (https://dlang.org/spec/template.html#function-templates) here, as that only works for function templates. That means the compiler won't deduce the template parameter type. So that alias would have to be called with quoteFoo!string("I'm a quoted sentence."); > alias singlequoteFoo(T) = fooImpl!('\'', T); > > void main() > { > quoteFoo(`"asdf"`); > singlequoteFoo(`'asdf'`); > } > > > ...was how I'd imagined it would look. > >>onlineapp.d(11): Error: template onlineapp.quoteFoo cannot deduce function from argument types !()(string), candidates are: >>onlineapp.d(6): onlineapp.quoteFoo(T) > > If I manually pass string as a template parameter, like quoteFoo!string("bar") or singlequoteFoo!string("baz"), it works. > > Can I do it this way or do I need to write wrapping functions? Instead of using aliases you could instantiate the function and use a function pointer to it (I hope my lingo is correct...). auto quoteFooString = &fooImpl!('"', string); and use it with quoteFooString("I'm another quoted sentence."); I'm trying to find a way to partially apply something to the template like //alias quoteFoo = ApplyLeft!(fooImpl, '"', AliasSeq!(int)); //quoteFoo(3); so the template fooImpl would only be partly instantiated with a '"', but the second argument would be left for when calling the function.. Unfortunately, above yields the error std/meta.d(1232): Error: template instance `Template!'"'` does not match template declaration fooImpl(char token, T)(const T line) ... Hm.. https://run.dlang.io/is/di8zjl import std.stdio; void fooImpl(char token, T)(const T line) { writefln("%s%s%s", token, line, token); } auto quoteFooString = &fooImpl!('"', string); auto singlequoteFooString = &fooImpl!('\'', string); void main() { quoteFooString("test quote"); singlequoteFooString("test single quote"); import std.meta; // std/meta.d(1232): Error: template instance `Template!'"'` does not match template //alias quoteFoo = ApplyLeft!(fooImpl, '"'); //quoteFoo(3); } |
July 01, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Anonymouse | On Saturday, 30 June 2018 at 21:11:54 UTC, Anonymouse wrote:
> I have a template that I want to provide easy aliases for, where the aliases includes (partially applies?) a template parameter.
>
>
> void fooImpl(char token, T)(const T line)
> {
> // ...
> }
>
> alias quoteFoo(T) = fooImpl!('"', T);
> alias singlequoteFoo(T) = fooImpl!('\'', T);
>
> void main()
> {
> quoteFoo(`"asdf"`);
> singlequoteFoo(`'asdf'`);
> }
I'd send you straight to std.meta.ApplyLeft, but it seems to do the wrong thing here, in that it doesn't handle IFTI. This thing does:
void fooImpl(int n, T)(const T line) { }
unittest {
alias fun = applyLeft!(fooImpl, 3);
fun(`aaa`);
applyLeft!(fooImpl, 3)(`aaa`);
}
template applyLeft(alias Fn, T...) {
auto applyLeft(U...)(U args) {
return Fn!T(args);
}
}
--
Simen
|
July 01, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On Sunday, 1 July 2018 at 01:48:15 UTC, Simen Kjærås wrote: > > I'd send you straight to std.meta.ApplyLeft, but it seems to do the wrong thing here, in that it doesn't handle IFTI. This thing does: > > void fooImpl(int n, T)(const T line) { } > > unittest { > alias fun = applyLeft!(fooImpl, 3); > fun(`aaa`); > applyLeft!(fooImpl, 3)(`aaa`); > } > > template applyLeft(alias Fn, T...) { > auto applyLeft(U...)(U args) { > return Fn!T(args); > } > } Would be nice if std.meta.ApplyLeft did the job here.. Is there no way of achieving that? It's current implementation looks like this: template ApplyLeft(alias Template, args...) { alias ApplyLeft(right...) = SmartAlias!(Template!(args, right)); } private template SmartAlias(T...) { static if (T.length == 1) { alias SmartAlias = Alias!T; } else { alias SmartAlias = AliasSeq!T; } } Would have to find a way to determine whether Template would resolve to a function or not. Can't find anything in Traits[1] or std.traits[2]. Template inspection looks rather limited : /. [1]: https://dlang.org/spec/traits.html [2]: https://dlang.org/phobos/std_traits.html |
July 01, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | On Sunday, 1 July 2018 at 09:46:55 UTC, Timoses wrote: > Would be nice if std.meta.ApplyLeft did the job here.. Is there no way of achieving that? [snip] > Would have to find a way to determine whether Template would resolve to a function or not. Can't find anything in Traits[1] or std.traits[2]. Template inspection looks rather limited : /. It is, but for a fairly good reason. This is perfectly valid D: template foo(int n) { static if (n == 0) { struct foo {} } else static if (n == 1) { enum foo = 24; } else { void foo() {} } } Given an uninstantiated foo, you can't know if it'll resolve to a function or not, so I guess some version of the template I wrote could be added to Phobos as ApplyLeftFn or something. -- Simen |
July 01, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On Sunday, 1 July 2018 at 11:55:15 UTC, Simen Kjærås wrote:
> On Sunday, 1 July 2018 at 09:46:55 UTC, Timoses wrote:
>> Would be nice if std.meta.ApplyLeft did the job here.. Is there no way of achieving that?
> [snip]
>> Would have to find a way to determine whether Template would resolve to a function or not. Can't find anything in Traits[1] or std.traits[2]. Template inspection looks rather limited : /.
>
> It is, but for a fairly good reason. This is perfectly valid D:
>
> template foo(int n) {
> static if (n == 0) {
> struct foo {}
> } else static if (n == 1) {
> enum foo = 24;
> } else {
> void foo() {}
> }
> }
>
> Given an uninstantiated foo, you can't know if it'll resolve to a function or not, so I guess some version of the template I wrote could be added to Phobos as ApplyLeftFn or something.
Aw, okay, then that won't work.
Still, this looks like it should work:
void foo(F, T)(T param) { writeln("Called with type: ", T.stringof); }
alias tfoo = ApplyLeft!(foo, int);
tfoo!string("hi");
// tfoo("hi"); // Error
|
July 01, 2018 Re: template alias that includes a parameter | ||||
---|---|---|---|---|
| ||||
Posted in reply to Timoses | On Sunday, 1 July 2018 at 13:01:20 UTC, Timoses wrote: > > Aw, okay, then that won't work. > > Still, this looks like it should work: > > void foo(F, T)(T param) { writeln("Called with type: ", T.stringof); } > alias tfoo = ApplyLeft!(foo, int); > > tfoo!string("hi"); > // tfoo("hi"); // Error https://issues.dlang.org/show_bug.cgi?id=9365 |
Copyright © 1999-2021 by the D Language Foundation