STLとDTL
なんか、id:shinichiro_hさんがトラバってくれてるので、STLの functional のポーティングしたのとか。
ちなみに id:shinichiro_h がせっかく教えてくれた mem_fun はまだ未実装m(__)m。
型コンテナ使った、汎用ファンクタも未実装。
ポーティングの際には、STL と DTL の両方を見ながらやったけど、若干ポリシーに違いがあるよう。
STL の functional は、ファンクタの基底クラスに unary_function, binary_function と命名してしまっており、型引数の順番も戻り値型が最後に来ているが、DTLの方は、
template Function(R, A0) { class Function ... template Function(R, A0, A1) { class Function
ちゅうふうに、テンプレート型引数の数でディスパッチし、戻り値型が先頭に来ている。
また、
template Function(R, A0, A1, A2) { class Function
といった、引数3つのファンクタも定義してる。
どういうことかっちうと、STL は、ファンクタは引数が2つまでのものしかサポートしてへんけど、DTL の方は可変個型引数に対する色気が見える。
というわけなので、id:shinichiro_h さんがポーティングしてくれた Loki の Typelist とか、TypeArray の コードを DTL 開発者に送ってあげれば、それが採用されて、可変個型引数のファンクタを DTL に入れてくれるかも……
ところで、関数オブジェクトだけ定義しても、それを渡す先のアルゴリズムが、ないとしょーがないわけですが、 algorithm のポーティングも部分的にしてないわけでゃないのすが、膨大すぎて、ねぇ。
module house.functor; import house.functions; import std.stdio; template FunctorMemberTypes(R, A) { alias R ResultType; alias A Arg1Type; } interface Functor(R, A) { mixin FunctorMemberTypes!(R, A); R opCall(A); } interface Functor(R, A1, A2) { mixin FunctorMemberTypes!(R, A1); alias A2 Arg2Type; R opCall(A1, A2); } /* interface Predicate(A) : Functor!(bool, A) {} interface Predicate(A1, A2) : Functor!(bool, A1, A2) {} */ template Predicate(A) { alias Functor!(bool, A) Predicate; } template Predicate(A1, A2) { alias Functor!(bool, A1, A2) Predicate; } /** * arithmetic */ class Plus(T) : Functor!(T, T, T) { T opCall(T arg1, T arg2) { return arg1 + arg2; } } class Minus(T) : Functor!(T, T, T) { T opCall(T arg1, T arg2) { return arg1 - arg2; } } class Multiplies(T) : Functor!(T, T, T) { T opCall(T arg1, T arg2) { return arg1 * arg2; } } class Divides(T) : Functor!(T, T, T) { T opCall(T arg1, T arg2) { return arg1 / arg2; } } class Modulus(T) : Functor!(T, T, T) { T opCall(T arg1, T arg2) { return arg1 % arg2; } } class Negate(T) : Functor!(T, T) { T opCall(T arg) { return -arg; } } /** * comparisons */ class EqualTo(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 == arg2; } } class NotEqualTo(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 != arg2; } } class Greater(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 > arg2; } } class Less(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 < arg2; } } class GreaterEqual(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 >= arg2; } } class LessEqual(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 <= arg2; } } /** * logical operation */ class LogicalAnd(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 && arg2; } } class LogicalOr(T) : Functor!(bool, T, T) { bool opCall(T arg1, T arg2) { return arg1 || arg2; } } class LogicalNot(T) : Functor!(bool, T) { bool opCall(T arg) { return !arg; } } /** * negators */ class Negator(A) : Functor!(bool, A) { private Functor!(bool, A) predicate; this(Functor!(bool, A) predicate) { this.predicate = predicate; } bool opCall(A arg) { return !predicate(arg); } } template not1(A) { Negator!(A) not1(Functor!(bool, A) predicate) { return new Negator!(A)(predicate); } } class Negator(A1, A2) : Functor!(bool, A1, A2) { private Functor!(bool, A1, A2) predicate; this(Functor!(bool, A1, A2) predicate) { this.predicate = predicate; } bool opCall(A1 arg1, A2 arg2) { return !predicate(arg1, arg2); } } template not2(A1, A2) { Negator!(A1, A2) not2(Functor!(bool, A1, A2) predicate) { return new Negator!(A1, A2)(predicate); } } /** * binders */ class Binder1st(O) : Functor!(O.ResultType, O.Arg2Type) { private O op; private O.Arg1Type arg1; this(O op, O.Arg1Type arg1) { this.op = op; this.arg1 = arg1; } O.ResultType opCall(O.Arg2Type arg2) { return op(arg1, arg2); } } template bind1st(O, A1) { Binder1st!(O) bind1st(O op, A1 arg1) in { static assert(is (A1 == O.Arg1Type)); } body { return new Binder1st!(O)(op, arg1); } } class Binder2nd(O) : Functor!(O.ResultType, O.Arg1Type) { private O op; private O.Arg2Type arg2; this(O op, O.Arg2Type arg2) { this.op = op; this.arg2 = arg2; } O.ResultType opCall(O.Arg1Type arg1) { return op(arg1, arg2); } } template bind2nd(O, A2) { Binder2nd!(O) bind2nd(O op, A2 arg2) in { static assert(is (A2 == O.Arg2Type)); } body { return new Binder2nd!(O)(op, arg2); } } /** * Adaptors */ class FuncPtrFunctor(R, A) : Functor!(R, A) { private R function(A) fp; this(R function(A) fp) { this.fp = fp; } R opCall(A arg) { return fp(arg); } } class FuncPtrFunctor(R, A1, A2) : Functor!(R, A1, A2) { private R function(A1, A2) fp; this(R function(A1, A2) fp) { this.fp = fp; } R opCall(A1 arg1, A2 arg2) { return fp(arg1, arg2); } } class DelegateFunctor(R, A) : Functor!(R, A) { private R delegate(A) dg; this(R delegate(A) dg) { this.dg = dg; } R opCall(A arg) { return dg(arg); } } class DelegateFunctor(R, A1, A2) : Functor!(R, A1, A2) { private R delegate(A1, A2) dg; this(R delegate(A1, A2) dg) { this.dg = dg; } R opCall(A1 arg1, A2 arg2) { return dg(arg1, arg2); } } template fpFunctor(R, A) { FuncPtrFunctor!(R, A) fpFunctor(R function(A) fp) { return new FuncPtrFunctor!(R, A)(fp); } } template fpFunctor(R, A1, A2) { FuncPtrFunctor!(R, A1, A2) fpFunctor(R function(A1, A2) fp) { return new FuncPtrFunctor!(R, A1, A2)(fp); } } template dgFunctor(R, A) { DelegateFunctor!(R, A) dgFunctor(R delegate(A) dg) { return new DelegateFunctor!(R, A)(dg); } } template dgFunctor(R, A1, A2) { DelegateFunctor!(R, A1, A2) dgFunctor(R delegate(A1, A2) dg) { return new DelegateFunctor!(R, A1, A2)(dg); } } template negateDelegate(A) { bool delegate (A) negateDelegate(bool delegate (A) dg) { bool not_dg(A arg1) { writefln("arg1 = %d, dg = %0X", arg1, &dg); return !dg(arg1); } return ¬_dg; } }