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

live on coliru

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

live on coliru

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

live on coliru

#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

Popular posts from this blog

inversion of control - Autofac named registration constructor injection -

verilog - Systemverilog dynamic casting issues -

ios - Change Storyboard View using Seague -