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 &not_dg;
	}
}