My template tuple code does not compile

Q. Schroll qs.il.paperinik at gmail.com
Tue Feb 26 23:49:27 UTC 2019


On Tuesday, 26 February 2019 at 22:56:37 UTC, Victor Porton wrote:
> On Tuesday, 26 February 2019 at 22:51:15 UTC, Q. Schroll wrote:
>> Grouping arguments could be done, but from my experience, it 
>> does not buy you anything; rather it makes it worse. Better 
>> just deal with heterogeneous stuff just like 
>> std.typecons.Tuple does.
>
> After fixing the error you pointed me, it does not work too:
>
> mixin ProviderParams!("S", ((int, "x"), (float, "y")));
>
> Also: Can I nevertheless group arguments?

No, not the way you do. The module std.meta defines AliasSeq as 
follows:

     alias AliasSeq(X...) = X;

It is literally equivalent to

     template AliasSeq(X...)
     {
         alias AliasSeq = X; // "eponymous template member"
     }

In

     mixin ProviderParams!("S", ((int, "x"), (float, "y")));

the parenthesized stuff like (int, "x") is invalid in terms of 
formal grammar. You could use AliasSeq!(int, "x") if you really 
want to display grouping in your source code. Note however that 
this does not do anything. The sequence is being flattened by the 
compiler, i.e.

     mixin ProviderParams!("S", AliasSeq!(AliasSeq!(int, "x"), 
AliasSeq!(float, "y")));

is exactly the same as

     mixin ProviderParams!("S", int, "x", float, "y");

which I wrote in my answer.

When you don't use a eponymous template member, you can access 
them manually:

     template Pack(X...)
     {
         alias Contents = X; // not "eponymous template member"
     }

Using this, you can create what I call packs. For some template 
T, while T!(AliasSeq!(int, bool), AliasSeq!(float, string, long)) 
is the same as writing T!(int, bool), the T!(Pack!(int, bool), 
Pack!(float, string, long)) is different from T!(int, bool, 
float, string, long). In the AliasSeq template, the eponymous 
template member feature of D immediately expands the sequence.

If the template T is defined like this:

     template T(Args...)
     { .. }

In the AliasSeq case, Args[0] is int, Args[1] is bool, Args[2] is 
float, ...
In the Pack case, Args[0] is Pack!(int, bool), Args[1] is 
Pack!(float, string, long), and Args[0].Contents[0] is int, 
Args[0].Contents[1] is bool, Args[1].Contents[0] is float ...

I've used Packs once to get the Cartesian product of an AliasSeq 
of Packs. It is a mess. I'd only use Packs when absolutely 
necessary; in your case, it does not seem so.

In your case, you seem to need some initial thing "S" and then 
pairs of things.

     template you_name_it(Arg, args...)
     if (args.length % 2 == 0) // ensures pairs
     {
         static foreach (i; args.length / 2)
         {
             // access the type by args[2*i]
             // access the name (or whatever) by args[2*i+1]
         }
     }

You could get the sequence of types and the sequence of names 
using

     alias Types = Stride!(2, args);
     alias Names = Stride!(2, args[1 .. $]);


More information about the Digitalmars-d-learn mailing list