c++ - Can I give different behaviours to boost::proto::tag types? -
i trying use boost proto lazily evaluate expressions, want able give different behaviours tags +, -, function etc.
function( terminal(8functionili2ee) , plus( multiplies( terminal(6tensorili0ee) , terminal(6tensorili1ee) ) , multiplies( terminal(6tensorili2ee) , terminal(6tensorili3ee) ) ) ) for tree above, want able specify how each of tree nodes should behave.
for eg.
struct context : proto::callable_context< context const > { // values replace tensors std::vector<double> args; // define result type of zero. // (this makes zero_context "callable".) typedef double result_type; // handle tensors: template<int i> double operator()(proto::tag::terminal, tensor<i>) const { std::cout << this->args[i] << std::endl; return this->args[i]; } template<int i> void operator()(proto::tag::plus) const { std::cout << " + " << std::endl; } }; when
double result = (_tensora + _tensorb)(10, 20); i expect output
10 + 20 but it's
10 20 any appreciated! :)
template<int i> void operator()(proto::tag::plus) const { std::cout << " + " << std::endl; } the template argument i non-deducible, overload never applicable. drop template argument:
void operator()(proto::tag::plus) const { std::cout << " + " << std::endl; } however want intercept binary operator. well. note it's binary. has 2 args:
template<size_t i, size_t j> void operator()(proto::tag::plus, proto::literal<tensor<i>>&, proto::literal<tensor<j>>&) const { std::cout << " + " << std::endl; } however, blocks further evaluation of expression tree. not wanted, right. so, let's simplisitic re-implementation:
template<size_t i, size_t j> double operator()(proto::tag::plus, proto::literal<tensor<i>>& a, proto::literal<tensor<j>>& b) const { auto va = (*this)(proto::tag::terminal{}, a.get()); std::cout << " + " << std::endl; auto vb = (*this)(proto::tag::terminal{}, b.get()); return va + vb; } generic, please
however, tells me wanted generic expressions. t1 + (t2 + t3) should work, (t2 + t3) no literal...
let's simplify delegating:
template<typename a, typename b> double operator()(proto::tag::plus, a& a, a& b) const { auto va = proto::eval(a, *this); std::cout << " + " << std::endl; auto vb = proto::eval(b, *this); return va + vb; } full sample
#include <boost/proto/proto.hpp> #include <vector> namespace proto = boost::proto; template <size_t n> struct tensor { }; template <size_t n, size_t m> tensor<n+m> operator+(tensor<n>, tensor<m>) { return {}; } struct context : proto::callable_context< context const > { using base_type = proto::callable_context<context const>; // values replace tensors std::vector<double> args { 0, 111, 222, 333 }; // define result type of zero. // (this makes zero_context "callable".) typedef double result_type; // handle tensors: template<size_t i> double operator()(proto::tag::terminal, tensor<i>) const { std::cout << this->args[i] << std::endl; return this->args[i]; } template<typename a, typename b> double operator()(proto::tag::plus, a& a, b& b) const { auto va = proto::eval(a, *this); std::cout << " + " << std::endl; auto vb = proto::eval(b, *this); return va + vb; } }; int main() { proto::literal<tensor<1> > t1; proto::literal<tensor<2> > t2; proto::literal<tensor<3> > t3; auto r = proto::eval(t1 + (t2 + t3), context()); std::cout << "eval(t1 + (t2 + t3)) = " << r << "\n"; } prints
111 + 222 + 333 eval(t1 + (t2 + t3)) = 666
Comments
Post a Comment