blob: d5928462f1eda15f45405a89a153647cfcb5f43c [file] [log] [blame]
@safe unittest
{
import std.meta;
import std.meta;
alias TL = AliasSeq!(int, double);
int foo(TL td) // same as int foo(int, double);
{
return td[0] + cast(int) td[1];
}
}
@safe unittest
{
import std.meta;
alias TL = AliasSeq!(int, double);
alias Types = AliasSeq!(TL, char);
static assert(is(Types == AliasSeq!(int, double, char)));
}
@safe unittest
{
import std.meta;
// Creates a compile-time sequence of function call expressions
// that each call `func` with the next variadic template argument
template Map(alias func, args...)
{
auto ref lazyItem() {return func(args[0]);}
static if (args.length == 1)
{
alias Map = lazyItem;
}
else
{
// recurse
alias Map = AliasSeq!(lazyItem, Map!(func, args[1 .. $]));
}
}
static void test(int a, int b)
{
assert(a == 4);
assert(b == 16);
}
static int a = 2;
static int b = 4;
test(Map!(i => i ^^ 2, a, b));
assert(a == 2);
assert(b == 4);
test(Map!((ref i) => i *= i, a, b));
assert(a == 4);
assert(b == 16);
static void testRef(ref int a, ref int b)
{
assert(a++ == 16);
assert(b++ == 256);
}
testRef(Map!(function ref(ref i) => i *= i, a, b));
assert(a == 17);
assert(b == 257);
}
@safe unittest
{
import std.meta;
// Without Alias this would fail if Args[0] was e.g. a value and
// some logic would be needed to detect when to use enum instead
alias Head(Args...) = Alias!(Args[0]);
alias Tail(Args...) = Args[1 .. $];
alias Blah = AliasSeq!(3, int, "hello");
static assert(Head!Blah == 3);
static assert(is(Head!(Tail!Blah) == int));
static assert((Tail!Blah)[1] == "hello");
}
@safe unittest
{
import std.meta;
alias a = Alias!(123);
static assert(a == 123);
enum abc = 1;
alias b = Alias!(abc);
static assert(b == 1);
alias c = Alias!(3 + 4);
static assert(c == 7);
alias concat = (s0, s1) => s0 ~ s1;
alias d = Alias!(concat("Hello", " World!"));
static assert(d == "Hello World!");
alias e = Alias!(int);
static assert(is(e == int));
alias f = Alias!(AliasSeq!(int));
static assert(!is(typeof(f[0]))); //not an AliasSeq
static assert(is(f == int));
auto g = 6;
alias h = Alias!g;
++h;
assert(g == 7);
}
@safe unittest
{
import std.meta;
import std.stdio;
void foo()
{
writefln("The index of long is %s",
staticIndexOf!(long, AliasSeq!(int, long, double)));
// prints: The index of long is 1
}
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, double, char);
alias TL = Erase!(long, Types);
static assert(is(TL == AliasSeq!(int, double, char)));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, long, int);
static assert(is(EraseAll!(long, Types) == AliasSeq!(int, int)));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, long, int, float);
alias TL = NoDuplicates!(Types);
static assert(is(TL == AliasSeq!(int, long, float)));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, long, int, float);
alias TL = Replace!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, long, int, float)));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, long, int, float);
alias TL = ReplaceAll!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, char, int, float)));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(int, long, long, int, float, byte, ubyte, short, ushort, uint);
alias TL = Reverse!(Types);
static assert(is(TL == AliasSeq!(uint, ushort, short, ubyte, byte, float, int, long, long, int)));
}
@safe unittest
{
import std.meta;
class A { }
class B : A { }
class C : B { }
alias Types = AliasSeq!(A, C, B);
MostDerived!(Object, Types) x; // x is declared as type C
static assert(is(typeof(x) == C));
}
@safe unittest
{
import std.meta;
class A { }
class B : A { }
class C : B { }
alias Types = AliasSeq!(A, C, B);
alias TL = DerivedToFront!(Types);
static assert(is(TL == AliasSeq!(C, B, A)));
alias TL2 = DerivedToFront!(A, A, A, B, B, B, C, C, C);
static assert(is(TL2 == AliasSeq!(C, C, C, B, B, B, A, A, A)));
}
@safe unittest
{
import std.meta;
import std.traits : Unqual;
alias TL = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort);
static assert(is(TL == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort)));
}
@safe unittest
{
import std.meta;
import std.traits : isIntegral;
static assert(!allSatisfy!(isIntegral, int, double));
static assert( allSatisfy!(isIntegral, int, long));
}
@safe unittest
{
import std.meta;
import std.traits : isIntegral;
static assert(!anySatisfy!(isIntegral, string, double));
static assert( anySatisfy!(isIntegral, int, double));
}
@safe unittest
{
import std.meta;
import std.traits : isNarrowString, isUnsigned;
alias Types1 = AliasSeq!(string, wstring, dchar[], char[], dstring, int);
alias TL1 = Filter!(isNarrowString, Types1);
static assert(is(TL1 == AliasSeq!(string, wstring, char[])));
alias Types2 = AliasSeq!(int, byte, ubyte, dstring, dchar, uint, ulong);
alias TL2 = Filter!(isUnsigned, Types2);
static assert(is(TL2 == AliasSeq!(ubyte, uint, ulong)));
}
@safe unittest
{
import std.meta;
import std.traits : isPointer;
alias isNoPointer = templateNot!isPointer;
static assert(!isNoPointer!(int*));
static assert(allSatisfy!(isNoPointer, string, char, float));
}
@safe unittest
{
import std.meta;
import std.traits : isNumeric, isUnsigned;
alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned);
static assert(storesNegativeNumbers!int);
static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint);
// An empty sequence of predicates always yields true.
alias alwaysTrue = templateAnd!();
static assert(alwaysTrue!int);
}
@safe unittest
{
import std.meta;
import std.traits : isPointer, isUnsigned;
alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned);
static assert( isPtrOrUnsigned!uint && isPtrOrUnsigned!(short*));
static assert(!isPtrOrUnsigned!int && !isPtrOrUnsigned!(string));
// An empty sequence of predicates never yields true.
alias alwaysFalse = templateOr!();
static assert(!alwaysFalse!int);
}
@safe unittest
{
import std.meta;
import std.algorithm.iteration : map;
import std.algorithm.sorting : sort;
import std.string : capitalize;
struct S
{
int a;
int c;
int b;
}
alias capMembers = aliasSeqOf!([__traits(allMembers, S)].sort().map!capitalize());
static assert(capMembers[0] == "A");
static assert(capMembers[1] == "B");
static assert(capMembers[2] == "C");
}
@safe unittest
{
import std.meta;
static immutable REF = [0, 1, 2, 3];
foreach (I, V; aliasSeqOf!([0, 1, 2, 3]))
{
static assert(V == I);
static assert(V == REF[I]);
}
}
@safe unittest
{
import std.meta;
// enum bool isImplicitlyConvertible(From, To)
import std.traits : isImplicitlyConvertible;
static assert(allSatisfy!(
ApplyLeft!(isImplicitlyConvertible, ubyte),
short, ushort, int, uint, long, ulong));
static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
ubyte, string, short, float, int) == AliasSeq!(ubyte, short)));
}
@safe unittest
{
import std.meta;
import std.traits : hasMember, ifTestable;
struct T1
{
bool foo;
}
struct T2
{
struct Test
{
bool opCast(T : bool)() { return true; }
}
Test foo;
}
static assert(allSatisfy!(ApplyRight!(hasMember, "foo"), T1, T2));
static assert(allSatisfy!(ApplyRight!(ifTestable, a => a.foo), T1, T2));
}
@safe unittest
{
import std.meta;
import std.traits : Largest;
alias Types = AliasSeq!(byte, short, int, long);
static assert(is(staticMap!(ApplyLeft!(Largest, short), Types) ==
AliasSeq!(short, short, int, long)));
static assert(is(staticMap!(ApplyLeft!(Largest, int), Types) ==
AliasSeq!(int, int, int, long)));
}
@safe unittest
{
import std.meta;
import std.traits : FunctionAttribute, SetFunctionAttributes;
static void foo() @system;
static int bar(int) @system;
alias SafeFunctions = AliasSeq!(
void function() @safe,
int function(int) @safe);
static assert(is(staticMap!(ApplyRight!(
SetFunctionAttributes, "D", FunctionAttribute.safe),
typeof(&foo), typeof(&bar)) == SafeFunctions));
}
@safe unittest
{
import std.meta;
alias ImInt0 = Repeat!(0, int);
static assert(is(ImInt0 == AliasSeq!()));
alias ImInt1 = Repeat!(1, immutable(int));
static assert(is(ImInt1 == AliasSeq!(immutable(int))));
alias Real3 = Repeat!(3, real);
static assert(is(Real3 == AliasSeq!(real, real, real)));
alias Real12 = Repeat!(4, Real3);
static assert(is(Real12 == AliasSeq!(real, real, real, real, real, real,
real, real, real, real, real, real)));
alias Composite = AliasSeq!(uint, int);
alias Composite2 = Repeat!(2, Composite);
static assert(is(Composite2 == AliasSeq!(uint, int, uint, int)));
alias ImInt10 = Repeat!(10, int);
static assert(is(ImInt10 == AliasSeq!(int, int, int, int, int, int, int, int, int, int)));
alias Big = Repeat!(1_000_000, int);
}
@safe unittest
{
import std.meta;
auto staticArray(T, size_t n)(Repeat!(n, T) elems)
{
T[n] a = [elems];
return a;
}
auto a = staticArray!(long, 3)(3, 1, 4);
assert(is(typeof(a) == long[3]));
assert(a == [3, 1, 4]);
}
@safe unittest
{
import std.meta;
alias Nums = AliasSeq!(7, 2, 3, 23);
enum Comp(int N1, int N2) = N1 < N2;
static assert(AliasSeq!(2, 3, 7, 23) == staticSort!(Comp, Nums));
}
@safe unittest
{
import std.meta;
alias Types = AliasSeq!(uint, short, ubyte, long, ulong);
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
static assert(is(AliasSeq!(uint, ubyte, ulong, short, long) == staticSort!(Comp,
Types)));
}
@safe unittest
{
import std.meta;
enum Comp(int N1, int N2) = N1 < N2;
static assert( staticIsSorted!(Comp, 2, 2));
static assert( staticIsSorted!(Comp, 2, 3, 7, 23));
static assert(!staticIsSorted!(Comp, 7, 2, 3, 23));
}
@safe unittest
{
import std.meta;
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long));
static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong));
}
@safe unittest
{
import std.meta;
static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long)));
static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long)));
static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short)));
static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short)));
alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong);
static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort)));
static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint)));
static assert(is(Stride!(-3, attribs) == AliasSeq!(ulong, long)));
}
@safe unittest
{
import std.meta;
// ApplyRight combined with Instantiate can be used to apply various
// templates to the same parameters.
import std.string : leftJustify, center, rightJustify;
alias functions = staticMap!(ApplyRight!(Instantiate, string),
leftJustify, center, rightJustify);
string result = "";
static foreach (f; functions)
{
{
auto x = &f; // not a template, but a function instantiation
result ~= x("hello", 7);
result ~= ";";
}
}
assert(result == "hello ; hello ; hello;");
}