I am trying understand the use of proto::fold to handle vararg expressions. As an experiment, I am trying to convert expressions of the form foo(a,b,c) to a string of the form "foo(a,b,c)". I currently have the following code where I treat the vararg expression as a fusion sequence and convert each parameter to a string using appropriate grammar. In the operator() of _foo_tostr, I have a case for each length of the vararg expression. Please let me know if there are better ways of doing this. #include <iostream> #include <boost/proto/proto.hpp> #include <boost/fusion/container/list/cons.hpp> #include <boost/fusion/include/cons.hpp> #include <boost/fusion/include/transform.hpp> #include <sstream> #include <string> using namespace std; namespace proto = boost::proto; namespace fusion = boost::fusion; unsigned ids; struct var { unsigned id; var() { id = ++ids; } }; struct foo {}; typedef proto::terminal<var>::type Var; typedef proto::terminal<foo>::type Foo; struct _var_tostr : proto::callable { typedef string result_type; result_type operator()(var const &v) const { stringstream sout; sout << "v" << v.id; return sout.str(); } }; struct var_tostr : proto::or_< proto::when<proto::terminal<var>, _var_tostr(proto::_value)>
{};
struct _foo_tostr : proto::callable { typedef string result_type; template<typename T> result_type operator()(T const &e) const { stringstream sout; sout << "foo("; if(fusion::size(e) == 1) { sout << ")"; } else if(fusion::size(e) == 2) { sout << var_tostr()(fusion::at_c<1>(e)) << ")"; } else if(fusion::size(e) == 3) { sout << var_tostr()(fusion::at_c<1>(e)) << ", " << var_tostr()(fusion::at_c<2>(e)) << ")"; } else if(fusion::size(e) == 4) { sout << var_tostr()(fusion::at_c<1>(e)) << ", " << var_tostr()(fusion::at_c<2>(e)) << ", " << var_tostr()(fusion::at_c<3>(e)) << ")"; } return sout.str(); } }; struct foo_tostr : proto::or_ < proto::when<proto::function<proto::terminal<foo>, proto::vararg<proto::terminal<var> > >, _foo_tostr(proto::_expr)> > {}; int main() { Var a, b, c; Foo f; cout << foo_tostr()(f(a,b,c)) << endl; }