D 2.0
About Japanese Translation

Last update Thu Feb 17 14:20:21 2011

std.typecons

このモジュールは、様々な型コンストラクタ -- つまり、 新しい汎用の型を構築するテンプレートを実装しています。

Synopsis:
// 値タプル
alias Tuple!(float, "x", float, "y", float, "z") Coord;
Coord c;
c[1] = 1;  // インデックスによるアクセス
c.z = 1;          // 指定された名前によるアクセス
alias Tuple!(string, string) DicEntry; // 名前は省略可能

// const/immutableオブジェクトへの、再束縛可能な参照
void bar()
{
    const w1 = new Widget, w2 = new Widget;
    w1.foo();
    // w1 = w2 はダメ; constオブジェクトは再束縛できない
    auto r = Rebindable!(const Widget)(w1);
    // r があたかもWidgetオブジェクトであるかのようにメソッド呼び出し
    r.foo();
    // r が他のオブジェクトを指すよう再束縛
    r = w2;
}

Source:
std/typecons.d

License:
Boost License 1.0.

Authors:
Andrei Alexandrescu, Bartosz Milewski, Don Clugston Shin Fujishiro

struct Unique(T);
リソースの唯一の所有権をカプセル化します。 所有権が移動してない限り、型Tを持つリソースが、スコープの終わりと同時に破棄されます。 所有権の移動は release による明示も、関数から Unique を返す暗黙の移動も可能です。リソースは多相的に振る舞うクラスオブジェクトであってもよく、 その場合は Unique も多相的に振る舞います。

Example:


this(RefT p);
右辺値をとるコンストラクタ。 指定された右辺値が(キャストなどによる)単なる左辺値のビューである場合を除き、 uniqueness を保証します。 典型的な使い方:
	Unique!(Foo) f = new Foo;


this(ref RefT p);
左辺値を取るコンストラクタ。コピー元をnullにします。 元の左辺値にさらに別のエイリアスが存在しない限り、 このnull化によって所有権のuniquenessが保証されます。

Unique release();
ユニークな右辺値を返します。Uniqueオブジェクトの保持する内容はnullになります。

RefT opDot();
保持するオブジェクトへのメンバアクセスを転送します。

struct Tuple(Specs...);
値のタプル。例えば Tuple!(int, string)intstring を格納したレコードです。Tuple は複数の値をまとめて、特に 関数から複数の値を返すのに使うことができます。obj がタプルなら、個々のメンバは先頭要素なら obj[0]、 次の要素なら obj[1] 、等々の構文でアクセスできます。

1始まりではなく0始まりの記法を選択した理由は、 タプルをコンパイル時のループ対象として (型タプル上のiterationのように) 自然に扱えるようにするためです。

Example:
Tuple!(int, int) point;
// 座標を代入
point[0] = 5;
point[1] = 6;
// 座標の読み取り
auto x = point[0];
auto y = point[1];
Tuple のメンバには名前をつけることができます。名前ありと名前無しのメンバを混ぜても構いません。 この場合も、上記の添え字によるアクセスは常に全てのフィールドについて可能です。

Example:
alias Tuple!(int, "index", string, "value") Entry;
Entry e;
e.index = 4;
e.value = "Hello";
assert(e[1] == "Hello");
assert(e[0] == 4);
名前付きタプルと名前なしタプルは異なる型として扱われます。 つまり、フィールドの名前が違うと違うタプル型になります。 フィールド名だけが違うタプルも、構造自体は同じですが、 型としては違う物になります。

Example:
Tuple!(int, "x", int, "y") point1;
Tuple!(int, int) point2;
assert(!is(typeof(point1) == typeof(point2))); // passes

alias Types;
タプルの要素型のリスト(型タプル)です。

template __ctor(U...) if (U.length == Types.length)
フィールドそれぞれにつき1つずつ値を受け取るコンストラクタです。 各々の引数は対応する要素型に代入可能である必要があります。

template __ctor(U) if (isTuple!(U))
互換性のある別のタプルを受け取る コンストラクタです。 対応する要素それぞれが代入可能である必要があります。

template opEquals(R) if (isTuple!(R))
同値性判定。

bool opEquals(R rhs);
同値性判定。

template opCmp(R) if (isTuple!(R))
順序判定

int opCmp(R rhs);
順序判定

template opAssign(R) if (isTuple!(R))
別のタプルからの代入。変換元のタプルのそれぞれの要素が、 変換先の対応するフィールドへ代入可能である必要があります。

void opAssign(R rhs);
別のタプルからの代入。変換元のタプルのそれぞれの要素が、 変換先の対応するフィールドへ代入可能である必要があります。

template slice(uint from,uint to)
タプルのスライスを取得します。

Example:
Tuple!(int, string, float, double) a;
a[1] = "abc";
a[2] = 4.5;
auto s = a.slice!(1, 3);
static assert(is(typeof(s) == Tuple!(string, float)));
assert(s[0] == "abc" && s.field[1] == 4.5);

string toString();
文字列への変換。

Tuple!(T) tuple(T...)(T args);
渡された引数でインスタンス化および初期化された Tuple オブジェクトを返します。

Example:
auto value = tuple(5, 6.7, "hello");
assert(value[0] == 5);
assert(value[1] == 6.7);
assert(value[2] == "hello");


template isTuple(T)
TTuple 構造体テンプレートのインスタンスであるときのみ true を返します。

template defineEnum(string name,T...)
真の名前付き列挙値を、 parseと文字列化のプリミティブ付きで定義します。

Example:
mixin(defineEnum!("Abc", "A", "B", 5, "C"));
これは以下のコードと同等です:

enum Abc { A, B = 5, C }
string enumToString(Abc v) { ... }
Abc enumFromString(string s) { ... }
enumToString 関数は、列挙値の被修飾名 "A", "B", "C" などを生成します。enumFromString 関数は "A", "B", "C" を受け取るとその値を返し、それ以外の文字列に対しては 例外を投げます。

基底型は次のように指定します:

mixin(defineEnum!("Abc", ubyte, "A", "B", "C", 255));
この場合、生成された enumubyte 表現を持つことになります。

template Rebindable(T) if (is(T == class) || is(T == interface) || isArray!(T))
Rebindable!(T) は、 T 型のオブジェクトと同じように振る舞うシンプルで効率的なラッパです。ただし、Rebindableは途中で別のオブジェクトを指すように 再代入が可能です。完全性を期すために、T が非constオブジェクト型の場合は、 Rebindable!(T) は単なる T へのaliasとなります。 T がそもそもクラス型でない場合は、Rebindable!(T) はコンパイルエラーとなります。

通常の const オブジェクト参照は再代入ができません:

class Widget { int x; int y() const { return a; } }
const a = new Widget;
a.y();          // 大丈夫
a.x = 5;        // エラー。const a は変更できない
a = new Widget; // エラー。const a は変更できない
しかしここで、Rebindable!(Widget) は最代入可能で、 その他の場面では const Widget とまったく同様に振る舞います:

auto a = Rebindable!(const Widget)(new Widget);
a.y();          // 大丈夫
a.x = 5;        // エラー。const a は変更できない
a = new Widget; // 大丈夫
const オブジェクトへの書き換え可能な参照が必要な場合に、Rebindable を使用すると良いでしょう。 たとえば、 inplace でconst参照をsortしたい場合などです。Rebindable が D の型システムの健全性を壊すことはなく、 cast の使用などに見られる類の危険もありません。



Rebindable!(T) rebindable(T)(T obj);
自動的な型推論で Rebindable を作るための便利関数です

Rebindable!(T) rebindable(T)(Rebindable!(T) obj);
この関数は単に渡された Rebindable をそのまま返します。 これは、ジェネリックなコードを書いているときに、渡されたオブジェクトが class なのか Rebindable なのか気にせず書ける利点があります。

char[] alignForSize(E...)(string[E.length] names);
指定されたメンバ宣言リストを、alignmentを保ったままでサイズが最小になるように並び替えます。 mixinできる宣言リストを返します。

Example:
struct Banner {
  mixin(alignForSize!(byte[6], double)(["name", "height"]));
}
80-bit 実数と、align(1) で宣言された構造体に関しては、 必ずしも最適な整列を行うとは限りません。

BUG:
bugzilla 2029 のため、(string[] names...) という引数リスト宣言ができません。 このため、現在のところ醜い配列リテラルを使う必要があります。

template BlackHole(Base)
BlackHole!BaseBase の派生クラスで、 Base の abstract 関数を自動的に何もしない空実装で実装した物となります。 各自動実装は、 返値型のデフォルト値をそのまま返すだけで他に何も行いません。

この名前は Sean M. Burke の Perl モジュール Class::BlackHole から採っています。

Example:
abstract class C
{
    int m_value;
    this(int v) { m_value = v; }
    int value() @property { return m_value; }

    abstract real realValue() @property;
    abstract void doSomething();
}

void main()
{
    auto c = new BlackHole!C(42);
    writeln(c.value);     // "42" を表示

    // abstract 関数はデフォルト実装:
    writeln(c.realValue); // "NaN"を表示
    c.doSomething();      // なにもしない
}

See Also:
AutoImplement, generateEmptyFunction

template WhiteHole(Base)
WhiteHole!BaseBase の派生クラスで、 全ての abstract 関数を例外を投げる関数で実装した物となります。 各自動実装は、呼ばれるとすぐに Error を投げ、returnすることはありません。 未実装の関数を埋めるのに役立ちます。

この名前は Michael G Schwern の Perl モジュール Class::WhiteHole から採っています。

Example:
class C
{
    abstract void notYetImplemented();
}

void main()
{
    auto c = new WhiteHole!C;
    c.notYetImplemented(); // Error を投げる
}

BUGS:
nothrow 関数は release モードではアボートしてしまう問題があります。 これはnothrow関数では実装が assert(0) で行われているためです。

See Also:
AutoImplement, generateAssertTrap

class AutoImplement(Base,alias how,alias what = isAbstractFunction): Base;
AutoImplement は (デフォルトで) クラスやinterface Base の 全てのabstractメンバを指定された方法で実装します。

Parameters:
how 関数の実装/オーバーライドの仕方を指定するテンプレートです

二つの引数が how に渡されます。型 Base と、 実装したい関数への alias です。これを受け取ると、how は関数実装のボディを文字列で返さなければなりません。

生成する関数本体文字列には、以下のキーワードを使えます:
  • a0, a1, …: 関数に渡される各引数
  • args: 引数のタプル
  • self: 関数自身へのalias
  • parent: (もしあれば) オーバーライドされる関数へのalias

暗黙のテンプレートプロパティの代わりに、テンプレート化された property 関数を使うというのも便利な方法です:
// オーバーライドする関数全てにログメッセージを付与
string generateLogger(C, alias fun)() @property
{
    enum qname = C.stringof ~ "." ~ __traits(identifier, fun);
    string stmt;

    stmt ~= q{ struct Importer { import std.stdio; } };
    stmt ~= `Importer.writeln("Log: ` ~ qname ~ `(", args, ")");`;
    static if (!__traits(isAbstractFunction, fun))
    {
        static if (is(typeof(return) == void))
            stmt ~= q{ parent(args); };
        else
            stmt ~= q{
                auto r = parent(args);
                Importer.writeln("--> ", r);
                return r;
            };
    }
    return stmt;
}
what どの関数を実装/オーバーライドするか決めるテンプレート

what に渡される引数は、 Base の非finalメンバ関数へのaliasです。what はbool値を返します。 true を返すと、その関数を implement/オーバーライドしたい、という意味になります。

// 何かreturnする関数かどうか見分ける
template hasValue(alias fun)
{
    enum bool hasValue = !is(ReturnType!(fun) == void);
}

Note:
生成されたコードは std.typecons モジュールのスコープに挿入されます。 したがって、std.typecons の外の有用な関数は生成コードでは使えません。 この問題を回避するには、必要なモジュールをローカルな構造体を作って import します。 例としては上記の generateLogger() テンプレートをご覧下さい。

BUGS:
  • コンストラクタの可変長引数がsuperに転送されません。
  • interface を深く継承すると、以下のようなエラーメッセージと共にコンパイルエラーになります: "Error: function std.typecons.AutoImplement!(Foo).AutoImplement.bar does not override any function". [Bugzilla 2525, Bugzilla 3525]
  • parent キーワードは、実際には基底クラスの対応するメンバの delegate です。 [Bugzilla 2540]
  • alias テンプレート引数を howwhat で使うとおかしなコンパイルエラーが出ることがあります。回避には、タプルテンプレート引数を使用します。 [Bugzilla 4217]

template generateEmptyFunction(C,func...)
template generateAssertTrap(C,func...)
AutoImplement の how に使える定義済みポリシーです。これらは BlackHoleWhiteHole の実装に用いられています。

enum RefCountedAutoInitialize;
RefCounted オブジェクトの自動初期化に関するオプション (詳しくは下の RefCounted の定義をご覧下さい)

no
自動初期化しない

yes
自動初期化する

struct RefCounted(T,RefCountedAutoInitialize autoInit = RefCountedAutoInitialize.yes) if (!is(T == class));
T を内部に保持する参照カウントオブジェクトです。 RefCounted はオブジェクトを指す参照をすべて追跡し、 カウントがゼロになると保持したオブジェクトを解放します。 RefCountedmallocfree を操作に使用します。

RefCounted は unsafe であり、使う場合は細心の注意が必要です。 内容への参照が RefCounted の管理の外へ漏れ出すことが内容にしてください。

autoInit オプションによって、アクセス時に オブジェクトが自動的に初期化されることが保証されます。autoInit == RefCountedAutoInitialize.yes (デフォルト) は便利ですが、 しかしアクセスの度にコストが発生します。autoInit == RefCountedAutoInitialize.no を指定すると、アクセスする前に refCountedIsInitialized または refCountedEnsureInitialized をユーザが呼び出しておく必要があります。これを怠ると null ポインタ参照になります。

Example:
// intsize_t のペア(後者が参照カウント)
// が動的に割り当てられる
auto rc1 = RefCounted!int(5);
assert(rc1 == 5);
// もう割り当てを行わない。参照カウントは1
auto rc2 = rc1;
// 参照のセマンティクス
rc2 = 42;
assert(rc1 == 42);
// rc1 と rc2 がスコープを抜けるとペアが解放される

template __ctor(A...) if (A.length > 0)
中身のオブジェクトを初期化するコンストラクタ

Postcondition:
refCountedIsInitialized

void opAssign(typeof(this) rhs);
void opAssign(T rhs);
代入演算子

T refCountedPayload();
中身のオブジェクトへの参照を返します。(autoInit == RefCountedAutoInitialize.yes) ならば、refCountedEnsureInitialized を呼び出します。そうでなければ,単に assert(refCountedIsInitialized) を確認します。alias refCountedPayload this; という形で使えるようになっているので、呼び出し側は RefCounted オブジェクトを単に T として使うことができます。

auto scoped(T, Args...)(Args args);
クラスオブジェクトを現在のスコープの内側に構築し、 new のオーバーヘッドを避けます。この機能は unsafe です。 作成したオブジェクトへの参照がスコープの外側に漏れないようにすることは、 ユーザーの責任です。

Example:
unittest
{
    class A { int x; }
    auto a1 = scoped!A();
    auto a2 = scoped!A();
    a1.x = 42;
    a2.x = 53;
    assert(a1.x == 42);
}