Use alias assignment in staticMap (#8039)

Use alias assignment in staticMap

Signed-off-by: Nathan Sashihara <n8sh@users.noreply.github.com>
Signed-off-by: Razvan Nitu <RazvanN7@users.noreply.github.com>
Merged-on-behalf-of: unknown
This commit is contained in:
Andrei Alexandrescu 2021-10-26 18:06:41 -04:00 committed by GitHub
parent fa14ddbc8c
commit b44c0c638a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -622,29 +622,40 @@ template DerivedToFront(TList...)
static assert(is(TL2 == AliasSeq!(C, C, C, B, B, B, A, A, A)));
}
private enum staticMapExpandFactor = 150;
private string generateCases()
{
string[staticMapExpandFactor] chunks;
chunks[0] = q{};
static foreach (enum i; 0 .. staticMapExpandFactor - 1)
chunks[i + 1] = chunks[i] ~ `F!(Args[` ~ i.stringof ~ `]),`;
string ret = `AliasSeq!(`;
foreach (chunk; chunks)
ret ~= `q{alias staticMap = AliasSeq!(` ~ chunk ~ `);},`;
return ret ~ `)`;
}
private alias staticMapBasicCases = AliasSeq!(mixin(generateCases()));
/**
Evaluates to $(D AliasSeq!(F!(Args[0]), F!(Args[1]), ..., F!(Args[$ - 1]))).
Evaluates to `AliasSeq!(fun!(args[0]), fun!(args[1]), ..., fun!(args[$ - 1]))`.
*/
template staticMap(alias F, Args ...)
template staticMap(alias fun, args...)
{
static if (Args.length < staticMapExpandFactor)
mixin(staticMapBasicCases[Args.length]);
else
alias staticMap = AliasSeq!(staticMap!(F, Args[0 .. $/2]), staticMap!(F, Args[$/2 .. $]));
version (__staticMap_simplest_but_buggy)
{
// @@@ BUG @@@
// The following straightforward implementation exposes a bug.
// See issue https://issues.dlang.org/show_bug.cgi?id=22421 and unittest below.
alias staticMap = AliasSeq!();
static foreach (arg; args)
staticMap = AliasSeq!(staticMap, fun!arg);
}
else version (__staticMap_simple_but_slow)
{
// This has a performance bug. Appending to the staticMap seems to be quadratic.
alias staticMap = AliasSeq!();
static foreach (i; 0 .. args.length)
staticMap = AliasSeq!(staticMap, fun!(args[i]));
}
else // Current best-of-breed implementation imitates quicksort
{
static if (args.length <= 8)
{
alias staticMap = AliasSeq!();
static foreach (i; 0 .. args.length)
staticMap = AliasSeq!(staticMap, fun!(args[i]));
}
else
{
alias staticMap = AliasSeq!(staticMap!(fun, args[0 .. $ / 2]), staticMap!(fun, args[$ / 2 .. $]));
}
}
}
///
@ -669,6 +680,14 @@ template staticMap(alias F, Args ...)
alias T = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort, long);
static assert(is(T == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort, long)));
// @@@ BUG @@@ The test below exposes failure of the straightforward use.
// See @adamdruppe's comment to https://github.com/dlang/phobos/pull/8039
template id(alias what) {
enum id = __traits(identifier, what);
}
enum A { a }
static assert(staticMap!(id, A.a) == AliasSeq!("a"));
}
// regression test for https://issues.dlang.org/show_bug.cgi?id=21088