Re: [proto] Nested Transforms

2011-02-28 Thread Eric Niebler
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

2011-02-28 Thread Nate Knight

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

2011-02-26 Thread Joel Falcou

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

2011-02-26 Thread Eric Niebler
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

2011-02-25 Thread Joel Falcou

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

2011-02-25 Thread Nate Knight
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