Category | Templates |
---|---|
Строительные блоки | Alias AliasSeq aliasSeqOf |
Фильтрация последовательности псевдонимов | Erase EraseAll Filter NoDuplicates |
Иерархия типов в последовательности псевдонимов | DerivedToFront MostDerived |
Преобразование последовательности псевдонимов | Repeat Replace ReplaceAll Reverse staticMap staticSort |
Поиск в последовательности псевдонимов | allSatisfy anySatisfy staticIndexOf |
Операторы для логических шаблонных предикатов | templateAnd templateNot templateOr |
Создание экземпляра шаблона | ApplyLeft ApplyRight |
Ссылки: Основано на идеях в Таблице 3.1 из Modern C++ Design, Andrei Alexandrescu (Addison-Wesley Professional, 2001)
Исходный код: std/meta.d
AliasSeq
(TList...)import std.meta; alias TL = AliasSeq!(int, double); int foo(TL td) // тоже самое, что int foo(int, double); { return td[0] + cast(int)td[1]; }
alias TL = AliasSeq!(int, double); alias Types = AliasSeq!(TL, char); static assert(is(Types == AliasSeq!(int, double, char)));
Alias
(alias a)Alias
(T)Alias
!4; //OK
// Без Alias это приведет к сбою, если параметр Арг.[0], например, является значением, // и понадобится некоторая логика для определения, когда использовать вместо этого enum 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");
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);
staticIndexOf
(T, TList...);
staticIndexOf
(alias T, TList...);
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 }
Erase
(T, TList...)Erase
(alias T, TList...)alias Types = AliasSeq!(int, long, double, char); alias TL = Erase!(long, Types); static assert(is(TL == AliasSeq!(int, double, char)));
EraseAll
(T, TList...)EraseAll
(alias T, TList...)alias Types = AliasSeq!(int, long, long, int); alias TL = EraseAll!(long, Types); static assert(is(TL == AliasSeq!(int, int)));
NoDuplicates
(TList...)alias Types = AliasSeq!(int, long, long, int, float); alias TL = NoDuplicates!(Types); static assert(is(TL == AliasSeq!(int, long, float))); // Bugzilla 14561: huge enums alias LongList = Repeat!(1500, int); static assert(NoDuplicates!LongList.length == 1);
Replace
(T, U, TList...)Replace
(alias T, U, TList...)Replace
(T, alias U, TList...)Replace
(alias T, alias U, TList...)alias Types = AliasSeq!(int, long, long, int, float); alias TL = Replace!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, long, int, float)));
ReplaceAll
(T, U, TList...)ReplaceAll
(alias T, U, TList...)ReplaceAll
(T, alias U, TList...)ReplaceAll
(alias T, alias U, TList...)alias Types = AliasSeq!(int, long, long, int, float); alias TL = ReplaceAll!(long, char, Types); static assert(is(TL == AliasSeq!(int, char, char, int, float)));
Reverse
(TList...)alias Types = AliasSeq!(int, long, long, int, float); alias TL = Reverse!(Types); static assert(is(TL == AliasSeq!(float, int, long, long, int)));
MostDerived
(T, TList...)class A { } class B : A { } class C : B { } alias Types = AliasSeq!(A, C, B); MostDerived!(Object, Types) x; // x объявлен как тип C static assert(is(typeof(x) == C));
DerivedToFront
(TList...)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)));
staticMap
(alias F, T...)import std.traits : Unqual; alias TL = staticMap!(Unqual, int, const int, immutable int); static assert(is(TL == AliasSeq!(int, int, int)));
allSatisfy
(alias F, T...)false
; шаблонный предикат должен быть выполним со всеми данными элементами.import std.traits : isIntegral; static assert(!allSatisfy!(isIntegral, int, double)); static assert( allSatisfy!(isIntegral, int, long));
anySatisfy
(alias F, T...)true
; шаблонный предикат должен быть выполним со всеми данными элементами.import std.traits : isIntegral; static assert(!anySatisfy!(isIntegral, string, double)); static assert( anySatisfy!(isIntegral, int, double));
Filter
(alias pred, TList...)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)));
templateNot
(alias pred)import std.traits : isPointer; alias isNoPointer = templateNot!isPointer; static assert(!isNoPointer!(int*)); static assert(allSatisfy!(isNoPointer, string, char, float));
templateAnd
(Preds...)true
для данного входа T тогда и только тогда, когда все переданные предикаты являются истиной для T.
import std.traits : isNumeric, isUnsigned; alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned); static assert(storesNegativeNumbers!int); static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint); // Пустой список предикатов всегда даёт true. alias alwaysTrue = templateAnd!(); static assert(alwaysTrue!int);
templateOr
(Preds...)true
для данного входа T тогда, когда хотя бы один переданный предикат возвращает истину для T.
import std.traits : isPointer, isUnsigned; alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned); static assert( isPtrOrUnsigned!uint && isPtrOrUnsigned!(short*)); static assert(!isPtrOrUnsigned!int && !isPtrOrUnsigned!(string)); // Пустой список предикатов всегда даёт true. alias alwaysFalse = templateOr!(); static assert(!alwaysFalse!int);
aliasSeqOf
(alias range)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");
static immutable REF = [0, 1, 2, 3]; foreach (I, V; aliasSeqOf!([0, 1, 2, 3])) { static assert(V == I); static assert(V == REF[I]); }
ApplyLeft
(alias Template, args...)ApplyRight
(alias Template, args...)Template | шаблон для частичного применения |
args | связываемые аргументы |
// 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)));
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));
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)));
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));
Repeat
(size_t n, TList...) if (n > 0)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)));
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]);
staticSort
(alias cmp, Seq...)Параметры: cmp = Шаблон, который возвращает bool (если первый аргумент меньше, чем второй) или int (-1 означает меньше, 0 означает равенство, 1 означает больше)
Seq = AliasSeq для сортировки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));
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)));