英語版
このページの英語版を見る

std.meta

操作するテンプレート テンプレートパラメーターシーケンス (別名エイリアスシーケンス)。
エイリアスシーケンスに対するいくつかの操作は、言語に組み込まれている、 例えば、S[i] は、シーケンスのインデックスi にある要素にアクセスする。 S[low .. high] 。 シーケンスのスライスを返す。
詳細はコンパイル時シーケンスを参照のこと。
注釈:このモジュールのいくつかのテンプレートは、単一の引数を取り、ブーリアン定数に評価される は1つの引数を取り、ブール定数に評価される。そのようなテンプレート はテンプレート述語と呼ばれる。
カテゴリー テンプレート
ビルディングブロック Alias AliasSeq aliasSeqOf
エイリアス・シーケンスのフィルタリング Erase EraseAll Filter NoDuplicates Stride
エイリアス配列の型階層構造 DerivedToFront MostDerived
エイリアス配列の変換 Repeat Replace ReplaceAll Reverse staticMap staticSort
エイリアス配列の検索 allSatisfy anySatisfy staticIndexOf
テンプレート述語 templateAnd templateNot templateOr staticIsSorted
テンプレートのインスタンス化 ApplyLeft ApplyRight Instantiate

参考文献 の表3.1のアイデアに基づいている。 モダンC++デザイン、 Andrei Alexandrescu(Addison-Wesley Professional、2001年)の表3.1の考え方に基づく。

出典 std/meta.d

template AliasSeq(TList...)
0個以上のエイリアスのシーケンスを作成する。これは、最も一般的に テンプレートのパラメータや引数として使われる。
Phobos の以前のバージョンでは、これはTypeTuple と呼ばれていた。
Examples:
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];
}
Examples:
alias TL = AliasSeq!(int, double);

alias Types = AliasSeq!(TL, char);
static assert(is(Types == AliasSeq!(int, double, char)));
Examples:
// 次の可変長テンプレート引数で`func`を呼び出す
// 一連の関数呼び出し式をコンパイル時に作成する
template Map(alias func, args...)
{
    auto ref lazyItem() {return func(args[0]);}

    static if (args.length == 1)
    {
        alias Map = lazyItem;
    }
    else
    {
        // 再帰する
        alias Map = AliasSeq!(lazyItem, Map!(func, args[1 .. $]));
    }
}

static void test(int a, int b)
{
    writeln(a); // 4
    writeln(b); // 16
}

static int a = 2;
static int b = 4;

test(Map!(i => i ^^ 2, a, b));
writeln(a); // 2
writeln(b); // 4

test(Map!((ref i) => i *= i, a, b));
writeln(a); // 4
writeln(b); // 16

static void testRef(ref int a, ref int b)
{
    writeln(a++); // 16
    writeln(b++); // 256
}

testRef(Map!(function ref(ref i) => i *= i, a, b));
writeln(a); // 17
writeln(b); // 257
template Alias(alias a)

template Alias(T)
任意のシンボル、"型"、またはコンパイル時式のalias
すべてを直接エイリアスできるわけではない。エイリアスを宣言することはできない。 エイリアスを宣言することはできない:
alias a = 4; //エラー
このテンプレートでは、単一のエンティティをエイリアスにすることができる:
alias b = Alias!4; //OK
See Also:
一度に複数のエイリアスを作成するには、次のようにする。 AliasSeq.
Examples:
// Aliasがなければ、Args[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");
Examples:
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]))); //AliasSeqではない
static assert(is(f == int));

auto g = 6;
alias h = Alias!g;
++h;
writeln(g); // 7
template staticIndexOf(args...) if (args.length >= 1)
args[0]args[1 .. $] args は型またはコンパイル時の値である。 見つからない場合は、-1 が返される。
Examples:
import std.stdio;

void foo()
{
    writefln("The index of long is %s",
             staticIndexOf!(long, AliasSeq!(int, long, double)));
    // 表示: longのインデックスは1である
}
template Erase(args...) if (args.length >= 1)
args[1 .. $] から作成され、 があればそれを取り除いたAliasSeq を返す、 args[0] があれば、それを取り除いたものを返す。
Examples:
alias Types = AliasSeq!(int, long, double, char);
alias TL = Erase!(long, Types);
static assert(is(TL == AliasSeq!(int, double, char)));
template EraseAll(args...) if (args.length >= 1)
args[1 .. $] から作成されたAliasSeq を、 があればすべて削除して返す、 args[0] があれば、それを取り除いたものを返す。
Examples:
alias Types = AliasSeq!(int, long, long, int);
static assert(is(EraseAll!(long, Types) == AliasSeq!(int, int)));
template NoDuplicates(args...)
AliasSeq args 。 を返す。
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = NoDuplicates!(Types);
static assert(is(TL == AliasSeq!(int, long, float)));
template Replace(T, U, TList...)

template Replace(alias T, U, TList...)

template Replace(T, alias U, TList...)

template Replace(alias T, alias U, TList...)
AliasSeq Tが見つかればUに置き換える。 Tが見つかればUに置き換える。
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = Replace!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, long, int, float)));
template ReplaceAll(args...)
args[2 .. $] から作成されたAliasSeq を返す。 args[0]args[1] に置き換える。
Examples:
alias Types = AliasSeq!(int, long, long, int, float);

alias TL = ReplaceAll!(long, char, Types);
static assert(is(TL == AliasSeq!(int, char, char, int, float)));
template Reverse(args...)
args から作成されたAliasSeq を、順序を逆にして返す。
Examples:
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)));
template MostDerived(T, TList...)
T から最も派生した型をTList から返す。 そのような型が見つからない場合は、T が返される。
Examples:
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));
template DerivedToFront(TList...)
TListの要素を、最も派生した型が最初に来るようにソートしたAliasSeq を返す。 の要素をソートして返す。
Examples:
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)));
template staticMap(alias fun, args...)
AliasSeq!(fun!(args[0]), fun!(args[1]), ..., fun!(args[$ - 1])) と評価される。
Examples:
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)));
template allSatisfy(alias F, T...)
与えられたすべての項目がテンプレート述語を満たすかどうかをテストする。 F!(T[0]) && F!(T[1]) && ... && F!(T[$ - 1]).
偽の結果に遭遇しても、評価は短絡されない。 テンプレート述語は、与えられたすべての項目でインスタンス化可能でなければならない。
template anySatisfy(alias F, T...)
与えられた項目がテンプレート述語を満たすかどうかをテストする。 F!(T[0]) || F!(T[1]) || ... || F!(T[$ - 1]).
真の結果に遭遇した場合、評価は短絡される。 テンプレート述語は、与えられた項目の一つでインスタンス化可能でなければならない。
template Filter(alias pred, args...)
AliasSeq テンプレート述語は、与えられた項目のいずれかでインスタンス化可能で なければならない。を返す。 AliasSeq を返す。
Examples:
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)));
template templateNot(alias pred)
渡されたテンプレート述語を否定する。
Examples:
import std.traits : isPointer;

alias isNoPointer = templateNot!isPointer;
static assert(!isNoPointer!(int*));
static assert(allSatisfy!(isNoPointer, string, char, float));
template templateAnd(Preds...)
論理ANDを用いていくつかのテンプレート述語を結合する。 を構築する。 がTに対して真である場合にのみ真と評価される新しい述語を構築する。
述語は左から右へ評価され、偽の結果が出た場合はショートカット方式で評価を中止する。 述語は左から右に評価され、偽の結果に遭遇した場合、評価をショートカットする。 この場合、後者のインスタンスはコンパイルする必要はない。
Examples:
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);
template templateOr(Preds...)
論理和を用いて複数のテンプレート述語を結合する。 を構築する。 のみが真と評価される新しい述語を構築する。
述語は左から右へ評価され、真の結果が得られた場合、ショートカット方式で評価を中止する。 述語は左から右に評価され、真の結果に遭遇した場合は評価をショートカットする。 この場合、後者のインスタンスはコンパイルする必要がない。
Examples:
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);
template aliasSeqOf(alias iter) if (isIterable!(typeof(iter)) && !isInfinite!(typeof(iter)))
foreach-iterable エンティティ(入力範囲など)をエイリアスシーケンスに変換する。
Parameters:
iter AliasSeq に変換するエンティティ。 foreach-statementを使用して反復可能でなければならない。
Returns:
iter を反復して生成された値を含むAliasSeq
Examples:
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");
Examples:
static immutable REF = [0, 1, 2, 3];
foreach (I, V; aliasSeqOf!([0, 1, 2, 3]))
{
    static assert(V == I);
    static assert(V == REF[I]);
}
template ApplyLeft(alias Template, args...)

template ApplyRight(alias Template, args...)
を部分的に適用する。 テンプレートを部分的に適用する。 をargsにバインドする。
argsが空の場合はidentity関数のように振る舞う。
Parameters:
Template テンプレートを部分的に適用する
args 引数をバインドする
Returns:
以下のアリティを持つテンプレート
Examples:
// 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)));
Examples:
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));
Examples:
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)));
Examples:
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));
template Repeat(size_t n, items...)
items をちょうどn 回繰り返すAliasSeq を作成する。
Examples:
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);
Examples:
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]));
writeln(a); // [3, 1, 4]
template staticSort(alias cmp, items...)
をソートする。 AliasSeqcmp を使用している。

パラメータ cmp =bool を返すテンプレート(最初の引数が2番目の引数より小さい場合)。 またはint (-1はより小さいことを意味し、0は等しいことを意味し、1はより大きいことを意味する)。

items = ソートする AliasSeqソートする

Returns:
ソートされたエイリアス列
Examples:
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));
Examples:
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)));
enum auto staticIsSorted(alias cmp, items...);
をチェックする。 AliasSeqcmp に従ってソートされているかどうかをチェックする。

パラメータ cmp =bool を返すテンプレート(最初の引数が2番目の引数より小さい場合)。 またはint (-1はより小さい、0は等しい、1はより大きい)。

Seq = チェックする AliasSeqをチェックする。

Returns:
true そうでない場合は、 。Seq false
Examples:
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));
Examples:
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));
template Stride(int stepSize, Args...) if (stepSize != 0)
stepSize を固定してシーケンス上をステップすることにより、Args のサブセットを選択する。 負の値stepSize は、最後の要素から反復を開始する。
Parameters:
stepSize 各反復でインクリメントする要素数。0 にはできない。
Args テンプレート引数。
Returns:
選択されたストライドでフィルタリングされたAliasSeq
Examples:
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)));
template Instantiate(alias Template, Params...)
与えられたテンプレートを与えられたパラメーターでインスタンス化する。
Dの構文上の制限を回避するために使用される。 T[0]!(...) の構文上の制限を回避するために使用される。 テンプレートが別のテンプレートを返す(例えば、Foo!(Bar)!(Baz) は許されない)。
Parameters:
Template インスタンス化するテンプレート。
Params テンプレートをインスタンス化するパラメータ。
Returns:
インスタンス化されたテンプレート。
Examples:
// ApplyRightをInstantiateと組み合わせることで、
// 同じパラメーターにさまざまなテンプレートを適用することができる。
import std.string : leftJustify, center, rightJustify;
alias functions = staticMap!(ApplyRight!(Instantiate, string),
                             leftJustify, center, rightJustify);
string result = "";
static foreach (f; functions)
{
    {
        auto x = &f; // テンプレートではなく、関数のインスタンス化である
        result ~= x("hello", 7);
        result ~= ";";
    }
}

writeln(result); // "hello  ; hello ;  hello;"