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