Boost.Proto をぺろぺろしてみる
ベクトル型の Expression Template を実装してみた。
すごく適当です。
こんな感じですか分かりません><
#include <iostream> #include <boost/proto/proto.hpp> namespace proto = boost::proto; struct vec{ int value[3]; }; vec make_vec(int x, int y, int z){ vec v = {x, y, z}; return v; } // 式の評価 struct vec_context : proto::callable_context<const vec_context>{ typedef int result_type; result_type operator ()(proto::tag::terminal, vec const& v) const{ return v.value[index_]; } result_type operator ()(proto::tag::terminal, int const& n) const{ return n; } vec_context(int index) : index_(index){} private: int index_; }; // 演算を評価するための定義 struct grammar : proto::or_< proto::terminal<proto::_>, proto::plus<grammar, grammar>, proto::minus<grammar, grammar>, proto::multiplies<grammar, grammar>, proto::divides<grammar, grammar> > {}; template<typename T> struct vec_expr; struct vec_domain : proto::domain<proto::generator<vec_expr>, grammar>{}; template<typename T> struct vec_expr : proto::extends<T, vec_expr<T>, vec_domain>{ explicit vec_expr(T const& t) : proto::extends<T, vec_expr<T>, vec_domain>(t){} }; // 演算の定義 template<typename> struct is_vec : boost::mpl::false_{}; template<> struct is_vec<vec> : boost::mpl::true_{}; BOOST_PROTO_DEFINE_OPERATORS(is_vec, vec_domain); // 式を評価する template<typename Expr> vec eval(Expr const& expr){ vec result = make_vec(0, 0, 0); for(int i = 0 ; i < 3 ; ++i){ result.value[i] = proto::eval( proto::as_expr<vec_domain>(expr), vec_context(i) ); } return result; } int main(){ vec v = make_vec(10, 20, 30); auto const& expr = v * 2 + 30; vec result = eval(expr); // vec result = eval(v + v + v); // C++03 の場合 std::cout << "x:" << result.value[0] << std::endl; std::cout << "y:" << result.value[1] << std::endl; std::cout << "z:" << result.value[2] << std::endl; return 0; }
[出力]
x:50 y:70 z:90
ポイントなのは、『式を評価する際に、要素ごとに展開する』ところですかね。
これで無駄なコピーが行われません。
評価を行うタイミングも重要。
今回は、vec 型に何も定義したくなかったんで、eval 関数で評価を行っていますが、代入演算子で評価するのがセオリーなのかしら?
domain 回りは写経しただけなので、実は何をやっているのかよく分かっていません……。
んーベクトル演算ごときに Boost.Proto を使うのはちょっと微妙…と思わなくもない。
サックリと使う分にはいいけど、本格的に使うとなるとちょっと難しそうな感じがする。
あと Booooost するし。
使えそうなところを見極めて使っていきたいにゃー。
[参照]
http://www.kmonos.net/alang/boost/classes/proto.html
http://d.hatena.ne.jp/faith_and_brave/20090501/1241167261
http://www.slideshare.net/fjnl/boost4-boostproto