Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 13, 2020 Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Hello, Was wondering if there was a simple, efficient way to unpack a variadic template argument. It needs to be efficient at runtime, and hopefully not use too much excessive CTFE. C++ has the "..." operator, is there something equivalent in D? template<class ...Args> void g(Args... args) { f(foo(args)...); // f(foo(args[0]), foo(args[1])); // etc } What would be a good way to write that in D, with it being as efficient (no copies or building structs etc) and not use too much CTFE. Needing to use `.map` or similar at CTFE would be an example of too much CTFE. void g(Args...)(auto ref Args args) { // ? } |
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jeff | On Thursday, 13 February 2020 at 07:06:49 UTC, Jeff wrote: > Hello, > > Was wondering if there was a simple, efficient way to unpack a variadic template argument. It needs to be efficient at runtime, and hopefully not use too much excessive CTFE. > > C++ has the "..." operator, is there something equivalent in D? > > template<class ...Args> > void g(Args... args) { > f(foo(args)...); // f(foo(args[0]), foo(args[1])); // etc > } > > What would be a good way to write that in D, with it being as efficient (no copies or building structs etc) and not use too much CTFE. Needing to use `.map` or similar at CTFE would be an example of too much CTFE. > > void g(Args...)(auto ref Args args) { > // ? > } Variadic template arguments unpack automatically in D, so you don't need to do anything special here: void g(Args...)(auto ref Args args) { import core.lifetime: forward; // like std::forward f(forward!args); } You can read more about variadic template arguments in this article: https://dlang.org/articles/ctarguments.html |
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Thursday, 13 February 2020 at 08:06:52 UTC, Paul Backus wrote:
> On Thursday, 13 February 2020 at 07:06:49 UTC, Jeff wrote:
>> Hello,
>>
>> Was wondering if there was a simple, efficient way to unpack a variadic template argument. It needs to be efficient at runtime, and hopefully not use too much excessive CTFE.
>>
>> C++ has the "..." operator, is there something equivalent in D?
>>
>> template<class ...Args>
>> void g(Args... args) {
>> f(foo(args)...); // f(foo(args[0]), foo(args[1])); // etc
>> }
>>
>> What would be a good way to write that in D, with it being as efficient (no copies or building structs etc) and not use too much CTFE. Needing to use `.map` or similar at CTFE would be an example of too much CTFE.
>>
>> void g(Args...)(auto ref Args args) {
>> // ?
>> }
>
> Variadic template arguments unpack automatically in D, so you don't need to do anything special here:
>
> void g(Args...)(auto ref Args args) {
> import core.lifetime: forward; // like std::forward
> f(forward!args);
> }
>
> You can read more about variadic template arguments in this article:
>
> https://dlang.org/articles/ctarguments.html
That would result in the call:
f( args[0], args[1], ... );
But the C++ version does the following:
f( foo(args[0]), foo(args[1]), ... );
They are different.
|
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jeff | On 2/13/20 11:29 AM, Jeff wrote:
> On Thursday, 13 February 2020 at 08:06:52 UTC, Paul Backus wrote:
>> Variadic template arguments unpack automatically in D, so you don't need to do anything special here:
>>
>> void g(Args...)(auto ref Args args) {
>> import core.lifetime: forward; // like std::forward
>> f(forward!args);
>> }
>>
>> You can read more about variadic template arguments in this article:
>>
>> https://dlang.org/articles/ctarguments.html
>
> That would result in the call:
>
> f( args[0], args[1], ... );
>
> But the C++ version does the following:
>
> f( foo(args[0]), foo(args[1]), ... );
>
> They are different.
the f(foo(args)...) syntax doesn't have a D equivalent.
I don't think it's possible to do without some form of mixin. While compile-time lists are available, they must be strictly made of things that are either CTFE expressions or symbols.
A possible mixin solution:
string doMixin(T...)(string formatspec)
{
string result;
import std.format: format;
static foreach(i; 0 .. T.length)
result ~= format(formatspec, __traits(identifier, T[i])) ~ ",";
return result[0 .. $-1]; // trim last comma
}
void g(T...)(T args) {
mixin("f(" ~ doMixin!args("foo(%s)") ~ ");");
}
-Steve
|
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 13 February 2020 at 17:13:31 UTC, Steven Schveighoffer wrote: > the f(foo(args)...) syntax doesn't have a D equivalent. It would be staticMap <http://dpldocs.info/experimental-docs/std.meta.staticMap.html> f(staticMap!(foo, args)) staticMap is a recursive template <http://dpldocs.info/experimental-docs/source/std.meta.d.html#L785> so no mixin stuff but it can get CT memory heavy in some cases due to all the instantiations. i say the compiler should just do this better. but really it works for the most part. |
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On 2/13/20 12:18 PM, Adam D. Ruppe wrote:
> On Thursday, 13 February 2020 at 17:13:31 UTC, Steven Schveighoffer wrote:
>> the f(foo(args)...) syntax doesn't have a D equivalent.
>
> It would be staticMap <http://dpldocs.info/experimental-docs/std.meta.staticMap.html>
>
> f(staticMap!(foo, args))
No, this does foo!(args[0]), foo!(args[1])...).
He wants a runtime call to each arg wrapped with foo.
One could do:
auto wrapFoo(alias arg)() { return foo(arg); }
and then f(staticMap!(wrapFoo, args));
But this means you have an additional function call (which could of course be inlined). It is a viable solution though (tested, and it does work).
-Steve
|
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 2/13/20 12:24 PM, Steven Schveighoffer wrote:
> But this means you have an additional function call (which could of course be inlined).
And I might add, an additional requirement to declare some other template (one of the huge drawbacks of std.meta, IMO).
Some syntax like expr(someTuple)... would be really cool to have in D.
Or something like arg => expr syntax for templates might be useful:
f(staticMap!(!a => foo(a), args)); // look ma, anonymous template!
-Steve
|
February 13, 2020 Re: Unpack Variadic Args? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thu, Feb 13, 2020 at 12:32:01PM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: [...] > Some syntax like expr(someTuple)... would be really cool to have in D. > > Or something like arg => expr syntax for templates might be useful: > > f(staticMap!(!a => foo(a), args)); // look ma, anonymous template! [...] Yes, yes, and yes! Anonymous templates would make std.traits and std.meta *much* easier to use. T -- "I'm running Windows '98." "Yes." "My computer isn't working now." "Yes, you already said that." -- User-Friendly |
Copyright © 1999-2021 by the D Language Foundation