On Thursday, 22 February 2018 at 19:26:54 UTC, Andrei Alexandrescu wrote:
After coding https://github.com/dlang/phobos/pull/6192 with AliasSeq, the experience has been quite pleasurable. However, in places the AliasSeq tends to expand too eagerly, leading to a need to "keep it together" e.g. when you need to pass two of those to a template.

I worked around the issue by nesting templates like this:

template Merge(T...)
{
    template With(U...)
    {
        static if (T.length == 0)
            alias With = U;
        else static if (U.length == 0)
            alias With = T;
        else static if (T[0] < U[0]
|| T[0] == U[0] && T[1].stringof <= U[1].stringof)
            alias With =
                AliasSeq!(T[0], T[1], Merge!(T[2 .. $]).With!U);
       else
            alias With =
                AliasSeq!(U[0], U[1], Merge!T.With!(U[2 .. $]));
    }
}

So instead of the unworkable Merge!(AliasSeq!(...), AliasSeq!(...)), one would write Merge!(AliasSeq!(...)).With!(AliasSeq!(...)).

The problem remains for other use cases, so I was thinking of adding to std.meta this simple artifact:

template PackedAliasSeq!(T...)
{
    alias expand = AliasSeq!T;
}

That way, everything stays together and can be expanded on demand.


Andrei

Yes, I love this stuff, lots of possibilities.

E.g.

import std.traits : isInstanceOf;
import std.meta : allSatisfy, AliasSeq, staticMap, Alias;

template Pack(T ...)
{
    alias expand = T;
    enum length = expand.length;
}

enum isPack(alias T) = isInstanceOf!(Pack, T);

template Head(alias P)
if (isPack!P)
{
    alias Head = Alias!(P.expand[0]);
}

template Tail(alias P)
if (isPack!P)
{
    alias Tail = Pack!(P.expand[1 .. $]);
}

template staticZip(Seqs ...)
if (Seqs.length >= 2 && allSatisfy!(isPack, Seqs))
{
    enum len = Seqs[0].length;
    static foreach (Seq; Seqs[1 .. $])
        static assert(Seq.length == len,
"All arguments to staticZip must have the same length");

    static if (len == 0)
        alias staticZip = AliasSeq!();
    else
        alias staticZip = AliasSeq!(Pack!(staticMap!(Head, Seqs)),
staticZip!(staticMap!(Tail, Seqs)));
}

Reply via email to