D 1.0   D 2.0
About Japanese Translation

Last update Tue Oct 16 09:58:55 2007

std.bind

関数に引数を束縛する。

References:
boost::bind

Authors:
Tomasz Stachowiak

Date:
November 28, 2006

DynArg!(0) _0;
DynArg!(1) _1;
DynArg!(2) _2;
DynArg!(3) _3;
DynArg!(4) _4;
DynArg!(5) _5;
DynArg!(6) _6;
DynArg!(7) _7;
DynArg!(8) _8;
DynArg!(9) _9;
'bind' 関数に渡されたときに、あとで動的に引数が入る場所を表すマーカーです。 Boostでは_1, _2, _3, ... と名前がついていますが、このライブラリでは _0, _1, _2, ... です。

struct Tuple(T...);
基本的な操作を備えたタプル構造体です。

template appendT(X)
最後に型Xを追加したタプル型を取得します

template append(X)
最後にX型の要素を追加したタプルを取得します

appendT!(X) append(X x);
最後にX型の要素を追加したタプルを取得します

template prependT(X)
先頭に型Xを追加したタプル型を取得します

template prepend(X)
先頭にX型の要素を追加したタプルを取得します

prependT!(X) prepend(X x);
先頭にX型の要素を追加したタプルを取得します

template concatT(T...)
現在のタプルの後ろに別のタプル型を追加します

struct Tuple();
空タプル構造体です

alias type;
空の組み込みのタプル

alias value;
空の組み込みのタプル

Tuple!(T) tuple(T...)(T t);
指定された引数から動的にタプルを作成

template isTypeTuple(T)
指定された型がTuple構造体かどうかを判定する

template minNumArgs(alias fn,fnT = typeof(&fn))
指定した関数の呼び出しに必要な最小の引数の個数を返します

class BoundFunc(FT,alias FAlias_,AllBoundArgs_);
束縛済みの関数用のコンテキストです

typeof(new BoundFunc!(FT,NullAlias,Tuple!(ArgList))) bind(FT, ArgList...)(FT fp, ArgList args);
bind() は、関数の引数を "束縛" できます。返値として、 引数の順番が違ったり個数が少ない関数を作り出して返します。関数の合成もbindで行うことができます。

bind() の使い方の構文は以下の通りです:

bind(関数かdelegateへのポインタ { , 引数 });

引数 は以下のいずれかです:
  • 静的/束縛 引数 (即値)
  • 別の束縛済み関数オブジェクト
  • 動的引数 _[0-9]、たとえば _0 や _3 や _9


結果は関数オブジェクトで、call(), func(), opCall() のいずれかで呼び出せます。 さらに便利な ptr() 関数も用意されていて、これはcall/func/opCallのdelegateを返します。

結果のdelegateは、動的引数が使われた個数とぴったり一致する数の引数を受け取ります。
- bind(&foo, _0, _1) // 2引数をとるdelegateになる
- bind(&foo, _1, _0) // 2引数をとるdelegateになる
- bind(&bar, _0, _1, _2, _0) // 3引数をとるdelegateになる


動的引数の型は束縛される関数の型から取得され、必要なら型の調整が行われます。 例えば、次のようなbindを行うと:
void foo(int a, long b)

// with:
bind(&foo, _0, _0)
最適な型の引数を1つとるdelegateになります。最適な型は std.typetuple.DerivedToFront を使って計算されますので、int と long なら long が選ばれます。一般に、bind は他の動的引数全てに暗黙変換できるような型を探そうとします。

注意:
数値型に関しては、明示的な、ただしユーザーには見える形でのキャストが行われます。


関数合成も直感的に記述できます:
bind(&f1, bind(&f2, _0))
これは引数を1つとって、それにf2を適用してから結果を引数にf1を呼び出すdelegateとなります。 数学的に言うと、これは関数合成です:
f1(f2(_0))
ある関数が複数回束縛されたならば、それは複数回呼び出されます。bind は遅延評価は行いません。なので
bind(&f3, bind(&f4, _0), bind(&f4, _0))
は呼ばれるたびにf4を二回呼び出して、f3への引数を用意し、次にf3を呼び出すdelegateになります



bind() のサポートするもう一つの機能は、タプルの自動展開です。つまり、次のような関数:
void foo(int a, int b)
Tuple!(int, int) bar()
をこうやってbindして書くことが可能になります。
bind(&foo, bind(&bar))
// あるいは
bind(&foo, tuple(23, 45))


template bindAlias(alias FT)
bindAlias() は bind() とよく似ていますが、もっと強力です。可能なら、bind() よりも bindAlias() を使ってください。


構文は:

bindAlias!(関数)(引数, 引数, 引数, 引数, ...);

bindAlias には、直接aliasを指定できるという利点があります。これによって、元々の関数のデフォルト引数を再利用することができ、ユーザーがその部分をわざわざ束縛する必要がなくなります。 これは、作ったdelegateが引数を省略してもしなくても呼び出せるようになっている、という意味ではありません。 bindAlias に指定された関数がデフォルト引数を持つ場合、その引数に関しては、何も指定せずとも自動で束縛される、という意味です。

さらに、bindAlias は out/inout 引数もうまく処理します。これは内部で扱いをポインタに変換することで実現されています。次のような関数は:
void foo(inout a)
こうやって束縛します:
int x;
bindAlias!(foo)(&x);


注意:
束縛時点で参照がnullなことをチェックする機能はありませんが、呼び出し時にはnullチェックが行われます。 これは、リリースモードでコンパイルするか version=BindNoNullCheck でコンパイルするとOFFにできます。