On 05/30/2012 06:25 PM, Eric Niebler wrote: > On 5/29/2012 3:29 PM, Karsten Ahnert wrote: >> On 05/29/2012 08:21 PM, Eric Niebler wrote: >>> On 5/29/2012 1:44 AM, Karsten Ahnert wrote: >>>> I have an arithmetic expression template where multiplication is >>>> commutative. Is there an easy way to order a chain of multiplications >>>> such that terminals with values (like proto::terminal< double >) appear >>>> at the beginning? For example that >>>> >>>> arg1 * arg1 * 1.5 * arg1 >>>> >>>> will be transformed to >>>> >>>> 1.5 * arg1 * arg1 * arg1 >>>> >>>> ? >>>> >>>> I can imagine some complicated algorithms swapping expressions and child >>>> expressions but I wonder if there is a simpler way. >>> >>> There is no clever built-in Proto algorithm for commutative >>> transformations like this, I'm afraid. I was going to suggest flattening >>> to a fusion vector and using fusion sort, but I see there is no fusion >>> sort! :-( Nevertheless, that seems like a promising direction to me. >>> Once you have the sorted vector, you should(?) be able to use >>> fusion::fold to build the correct proto tree from it. >> >> Ok, this looks promising. But I failed to get proto::fold to work. As a >> first step I tried to flatten an expression and reconstruct it with >> proto::fold: >> >> struct back_fold : >> proto::fold< >> proto::_ , >> proto::_state , >> proto::functional::make_multiplies( proto::_state , proto::_ ) >> > { }; >> >> template< class Expr > >> void eval( const Expr &e ) >> { >> back_fold b; >> proto::display_expr( >> b( proto::flatten( e ) , proto::_make_terminal()( 1.0 ) ) >> ); >> } >> >> eval( 2.0 * arg1 * arg1 * arg1 * 1.0 ); >> >> Unfortunately this does not compile. Any ideas what is wrong here? > > Yes, I know. I said you should use fusion::fold, not proto::fold. Once > you flatten a proto expression, you get a fusion sequence. That means > you have to use a fusion algorithm on it. Proto's transforms expect > their first parameter to be proto expression trees. The result of > proto::flatten is emphatically not. >
ok, this makes sense. Next trial: template< typename I > struct placeholder : I {}; proto::terminal< placeholder< mpl::size_t< 0 > > >::type const arg1 = {}; proto::display_expr( fusion::fold( proto::flatten( arg1 ) , proto::functional::make_terminal()( 1.0 ) , proto::functional::make_multiplies() ) ); gives a compilation error: /boost/proto/fusion.hpp:86:20: error: no type named ‘proto_tag’ in ‘const struct placeholder<mpl_::size_t<0ul> > It is difficult for me to figure out what happens here. Any ideas? _______________________________________________ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto