Expression Template(式テンプレート)を使って、遅延評価を実現する

式構造自体を保存し、必要な際に評価するための枠組み。「Expression Template」でググると色々例が出てくるが、大体行列・ベクトルを扱ったものばかりなので、がんばって”スカラー”評価をする用のクラスを書いてみた。正しくなさげ・最適化の余地ありだと思うので、突っ込んで頂けると嬉しいです。

自分用To-Do

  • コンストラクタを呼ぶ回数を減らしたい
  • 演算子の多重定義をもっと書きやすく
  • 一時変数(Expression<...>)が数式を伸ばすほど伸びてしまうので、もっと簡単に書きたい。
#include<iostream>
using namespace std;
//値を保持するクラス
class Value
{
public: 
	explicit Value(double x) : x_(x){cout << "Constructor of Value type as " << x << endl;}
	double Evaluate() {return x_;}
private :
	double x_;
};
//数式表現を保存しておくクラス
template < class L, class Operator, class R >
class Expression
{
public :
	Expression(L & l, R  & r) : l_(l), r_(r) { }
	Value Evaluate(){return Operator::Apply(l_.Evaluate(), r_.Evaluate());}
private : 
	L & l_;
	R & r_;
};
//実際の計算用演算子
class Plus
{
public :
	static Value Apply(Value &lhs, Value &rhs){return Value(lhs.Evaluate() + rhs.Evaluate());}
	static Value Apply(Value &lhs, double rhs){return Value(lhs.Evaluate() + rhs);}
	static Value Apply(double lhs, Value &rhs){return Value(lhs + rhs.Evaluate());}
	static Value Apply(double lhs, double rhs){return Value(lhs + rhs);}
};
class Multiply
{
public :
	static Value Apply(Value &lhs, Value & rhs){return Value(lhs.Evaluate() * rhs.Evaluate());}
	static Value Apply(Value &lhs, double rhs){return Value(lhs.Evaluate() * rhs);}
	static Value Apply(double lhs, Value & rhs){return Value(lhs * rhs.Evaluate());}
	static Value Apply(double lhs, double rhs){return Value(lhs * rhs);}
};
//各種オペレーターの多重定義
template < class L, class R>
Expression<L, Plus, R> operator+(L & lhs, R & rhs){return Expression<L, Plus, R>(lhs, rhs) ;	}
template < class L, class R>
Expression<L, Multiply, R> operator*(L & lhs, R & rhs){return Expression<L, Multiply, R>(lhs, rhs) ;	}

//メイン関数
int main()
{
	//適当な値を用意
	Value x(1);
	Value y(2);
	Value z(3);
	//数式表現を構築
	Expression<Value, Plus, Expression<Value, Multiply, Value>> f = x + y * z;
	//実際に評価(遅延評価!)
	cout << "Evaluate!!!" << endl;
	cout <<  f.Evaluate().Evaluate() << endl;
	return 0;
}

実行結果

Constructor of Value type as 1
Constructor of Value type as 2
Constructor of Value type as 3
Evaluate!!!
Constructor of Value type as 6
Constructor of Value type as 7
7

参考
http://shnya.jp/blog/?p=338
Expression templates - Wikipedia
More C++ Idioms/式テンプレート(Expression-template) - Wikibooks