Concatenating compile time sequences
H. S. Teoh
hsteoh at quickfur.ath.cx
Sat Mar 2 02:38:09 UTC 2019
On Sat, Mar 02, 2019 at 02:16:22AM +0000, Victor Porton via Digitalmars-d-learn wrote:
> I try to split a compile time sequence of types and names into a
> sequence consisting of two-element subsequences (each of type and
> name).
>
> That is, I want to transform:
>
> (int, "x", float, "y", double, "z")
>
> into
>
> (AliasSeq!(int, "x"), AliasSeq!(float, "y"), AliasSeq!(double, "z"))
Keep in mind that sequences produced by AliasSeq are auto-expanding,
meaning the above construct will automatically flatten into a flat
AliasSeq!(int, "x", float, "y", double, "z"). If that's not what you
want, you need to wrap your subsequences in a separate, non-eponymous
template.
> I am trying like this:
>
> private alias enum processFields() = AliasSeq!();
I'm not sure what "alias enum" is supposed to mean; is that a typo?
Surely you mean just "alias"?
> private alias enum processFields(T, name, Fields...) =
> AliasSeq!(AliasSeq!(T, name), processFields!(Fields));
This line doesn't do what you think it does, because of auto-expansion.
It's essentially exactly the same thing as:
private alias processFields(T, name, Fields...) =
AliasSeq!(T, name, processFields!(Fields));
i.e., the nested AliasSeq has no effect.
> But the above would (as I understand) make AliasSeq! returned by the
> recursively called processFields an element of the parent sequence
> rather than its tail subsequence as it should.
If you want anything that retains a nested structure, you cannot use
AliasSeq because of auto-expansion. You need to define your own,
non-eponymous template container, e.g.:
template MySeq(T...) {
alias data = T;
}
alias processFields(T, name, Fields...) =
AliasSeq!(MySeq!(T, name), MySeq!(processFields!(Fields)));
The MySeq!(...) "protect" their contents from flattening into the outer
list, while the outer AliasSeq causes individual MySeq!(...)'s to be
promoted to the top level sequence rather than producing a tree-like
structure.
Note that to access the data inside a MySeq, you'll have to use .data,
for example:
alias fields = processFields!(int, "x", float, "y");
alias type0 = fields[0].data[0]; // int
string name0 = fields[0].data[1]; // "x"
alias type1 = fields[1].data[0]; // float
string name1 = fields[1].data[1]; // "y"
Hope this helps.
T
--
Windows: the ultimate triumph of marketing over technology. -- Adrian von Bidder
More information about the Digitalmars-d-learn
mailing list