Re: [proto] Nested Transforms
On 2/28/2011 11:40 PM, Nate Knight wrote: > > On Feb 26, 2011, at 4:55 AM, Eric Niebler wrote: >> >> I think I know what's causing this. Can you try compiling with >> BOOST_PROTO_STRICT_RESULT_OF? > > Eric, > > Thanks for the information. Compiling with BOOST_PROTO_STRICT_RESULT_OF > allows the first commented line to compile. I guess we'll wait to hear from > Joel about > the impact of this change on the run times of his library. > > The second commented line does not compile. This seems to be because there > are no > 'const Expr&' overloads of boost::proto::transform::operator(). Is this > correct? The pertinent > part of the compiler error (from clang) is That's correct. This code compiles on trunk. I made a late fix that didn't make it into 1.46. If we ship a point release, I'll merge it over. But even with this fix, it can crop up in other circumstances. This is a Proto gotcha. It's missing a bunch of overloads in the interest of compile times (transform_impl is instantiated /everywhere/), but I need to reconsider this because you're not the first to get bitten by this. If you file a bug, I'll get around to it eventually. Some day, I'll use rvalue refs and this problem will just go away. -- Eric Niebler BoostPro Computing http://www.boostpro.com ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto
Re: [proto] Nested Transforms
On Feb 26, 2011, at 4:55 AM, Eric Niebler wrote: > On 2/26/2011 8:18 AM, Nate Knight wrote: >> >> int main() >> { >>la::state_type x = {1.0,2.0}; >>la::state_type const& xc = x; >> >>// this compiles >>la::EvalOpt()( lit(x)[1] ); >> >>// this fails to compile >>//la::EvalOpt()( lit(xc)[1] ); >> >>// this fails to compile >>//_default<>()( la::Optimize()( boost::proto::lit(x)[1] ) ); >> >>// this compiles >>_default<>()( as_expr( la::Optimize()( boost::proto::lit(x)[1] ) ) ); >> } > > > I think I know what's causing this. Can you try compiling with > BOOST_PROTO_STRICT_RESULT_OF? > Eric, Thanks for the information. Compiling with BOOST_PROTO_STRICT_RESULT_OF allows the first commented line to compile. I guess we'll wait to hear from Joel about the impact of this change on the run times of his library. The second commented line does not compile. This seems to be because there are no 'const Expr&' overloads of boost::proto::transform::operator(). Is this correct? The pertinent part of the compiler error (from clang) is boost/proto/transform/impl.hpp:96:9: note: candidate function [with Expr = boost::proto::exprns_::expr &, boost::proto::domainns_::default_domain> &, const boost::proto::exprns_::expr, 0> &>, 2>] not viable: no known conversion from 'typename boost::proto::detail::apply_transform &, default_domain> &, expr, 0> >, 2> &)>::result_type' (aka 'boost::proto::exprns_::expr &, boost::proto::domainns_::default_domain> &, const boost::proto::exprns_::expr, 0> &>, 2>') to 'boost::proto::exprns_::expr &, boost::proto::domainns_::default_domain> &, const boost::proto::exprns_::expr, 0> &>, 2> &' for 1st argument BOOST_PROTO_TRANSFORM_(PrimitiveTransform, X) Nate ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto
Re: [proto] Nested Transforms
On 26/02/11 12:55, Eric Niebler wrote: But maybe it wouldn't hurt. Maybe RVO kicks in. It's worth testing. Joel F., are you listening? Yours is probably the most performance sensitive application of Proto. Can you try compiling with BOOST_PROTO_STRICT_RESULT_OF and let us know if there's a perf hit? Will do asap and report ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto
Re: [proto] Nested Transforms
On 2/26/2011 8:18 AM, Nate Knight wrote: > I'm trying to understand why the two commented out lines fail to compile. It > seems to me > that ideally they would compile, but I may be missing some constraint that > makes these > lines incorrect. In the first case, it seems like the return type of the > default subscript evaluator > is being computed incorrectly. The second one is not as interesting, but I > curious why it > doesn't compile. > > I'm compiling against 1.45 with gcc 4.5. > > Thanks for any help. > > #include > #include > #include > > using namespace boost::proto; > > namespace la > { > typedef std::tr1::array< double, 2 > state_type; > > struct Distribute: > or_< > when, _make_subscript(_, _state)>, > terminal<_>, > nary_expr<_, vararg > > > > {}; > > struct Optimize: > or_< > when< > subscript >, > Distribute(_left, _right) > >, > nary_expr<_, vararg >, > terminal<_> > > > {}; > > // optimize and then evaluate > struct EvalOpt: when<_, _default<>(Optimize)> {}; > } > > int main() > { > la::state_type x = {1.0,2.0}; > la::state_type const& xc = x; > > // this compiles > la::EvalOpt()( lit(x)[1] ); > > // this fails to compile > //la::EvalOpt()( lit(xc)[1] ); > > // this fails to compile > //_default<>()( la::Optimize()( boost::proto::lit(x)[1] ) ); > > // this compiles > _default<>()( as_expr( la::Optimize()( boost::proto::lit(x)[1] ) ) ); > } I think I know what's causing this. Can you try compiling with BOOST_PROTO_STRICT_RESULT_OF? What's going on: Proto is cutting corners in the interest of performance. Consider the actual implementation of the _value transform: struct _value : transform<_value> { template struct impl : transform_impl { typedef typename result_of::value::type result_type; /// Returns the value of the specified terminal expression. /// \pre arity_of\::value == 0. /// \param e The current expression. /// \return proto::value(e) /// \throw nothrow #ifdef BOOST_PROTO_STRICT_RESULT_OF typename mpl::if_c::value, result_type &, result_type>::type #else typename result_of::value::type #endif operator ()( typename impl::expr_param e , typename impl::state_param , typename impl::data_param ) const { return proto::value(e); } }; }; Notice the PP grossness. The type that the transform *claims* to return differs from the type it actually returns. It does that to avoid making copies. The problem is that the compile-time computation of your transform does something slightly different than the runtime one. In most cases, its harmless. Not in yours. You're an innocent bystander who got cross in the crossfire. Sorry. So what to do? This is clearly a bug in proto. But I hesitate to fix it because I worry about the performance implications. It's not so bad for terminals, but _child_c has the same problem, and if the _child_c transform suddenly started returning whole sub-trees by value, it could really hurt. But maybe it wouldn't hurt. Maybe RVO kicks in. It's worth testing. Joel F., are you listening? Yours is probably the most performance sensitive application of Proto. Can you try compiling with BOOST_PROTO_STRICT_RESULT_OF and let us know if there's a perf hit? -- Eric Niebler BoostPro Computing http://www.boostpro.com ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto
Re: [proto] Nested Transforms
On 26/02/11 02:18, Nate Knight wrote: I'm trying to understand why the two commented out lines fail to compile. It seems to me that ideally they would compile, but I may be missing some constraint that makes these lines incorrect. In the first case, it seems like the return type of the default subscript evaluator is being computed incorrectly. The second one is not as interesting, but I curious why it doesn't compile. I'm compiling against 1.45 with gcc 4.5. Thanks for any help. Do you have the compilation output for each failure separately. I dont have a compiler handy atm. ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto
[proto] Nested Transforms
I'm trying to understand why the two commented out lines fail to compile. It seems to me that ideally they would compile, but I may be missing some constraint that makes these lines incorrect. In the first case, it seems like the return type of the default subscript evaluator is being computed incorrectly. The second one is not as interesting, but I curious why it doesn't compile. I'm compiling against 1.45 with gcc 4.5. Thanks for any help. #include #include #include using namespace boost::proto; namespace la { typedef std::tr1::array< double, 2 > state_type; struct Distribute: or_< when, _make_subscript(_, _state)>, terminal<_>, nary_expr<_, vararg > > {}; struct Optimize: or_< when< subscript >, Distribute(_left, _right) >, nary_expr<_, vararg >, terminal<_> > {}; // optimize and then evaluate struct EvalOpt: when<_, _default<>(Optimize)> {}; } int main() { la::state_type x = {1.0,2.0}; la::state_type const& xc = x; // this compiles la::EvalOpt()( lit(x)[1] ); // this fails to compile //la::EvalOpt()( lit(xc)[1] ); // this fails to compile //_default<>()( la::Optimize()( boost::proto::lit(x)[1] ) ); // this compiles _default<>()( as_expr( la::Optimize()( boost::proto::lit(x)[1] ) ) ); } ___ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto