boost::proto user guide - compile error creating a lazy function
::type
Hi,
I am going through proto user guide. I am getting compiling error for the
following piece code (it's pretty much copy and pasted from the guide). I
used 1.40 and gcc.
#include <iostream>
#include
Hi Tom, comments inline ... Tom Babbin wrote:
Hi,
I am going through proto user guide. I am getting compiling error for the following piece code (it's pretty much copy and pasted from the guide). I used 1.40 and gcc.
#include <iostream> #include
#include #include #include #include <cmath> #include <vector> namespace proto = boost::proto;
template<int I> struct placeholder {};
// Define some placeholders proto::terminal< placeholder< 1 > >::type const _1 = {{}}; proto::terminal< placeholder< 2 > >::type const _2 = {{}};
struct calculator_context : proto::callable_context< calculator_context const > { // Values to replace the placeholders std::vector<double> args;
// Define the result type of the calculator. // (This makes the calculator_context "callable".) typedef double result_type;
// Handle the placeholders: template<int I> double operator()(proto::tag::terminal, placeholder) const
Should be placeholder<I> here ----------------^^^^^^^^^^^
{ return this->args[I]; } };
// Define a pow_fun function object template<int Exp> struct pow_fun { typedef double result_type; double operator()(double d) const { return std::pow(d, Exp); } };
// Define a lazy pow() function for the calculator DSEL. // Can be used as: pow< 2 >(_1) template
typename proto::function< typename proto::terminal ::type , Arg const & ::type
Return type needs a const.
pow1(Arg const &arg) { typedef typename proto::function< typename proto::terminal
::type , Arg const & >::type result_type; result_type result = {{{}}, arg}; return result; }
int main() { calculator_context ctx; ctx.args.push_back(3);
std::cout << boost::proto::eval( pow1<2>( _1 ), ctx );
The problem is that proto::eval() takes its first argument by non-const reference. The temporary expression returned by pow1 doesn't bind to it as it's defined in the users' guide. Adding a const-qualification to the return type solves the problem. I'll update the docs for 1.41. Thanks for the report. -- Eric Niebler BoostPro Computing http://www.boostpro.com
The problem is that proto::eval() takes its first argument by non-const reference. The temporary expression returned by pow1 doesn't bind to it as it's defined in the users' guide. Adding a const-qualification to the return type solves the problem.
I'll update the docs for 1.41. Thanks for the report.
Hi, Eric, Thanks for the quick response. Adding a const does fix the problem. However, I am relatively new to meta programming. How come a const expression binds to the first argument of eval, while a non-const does not? Thanks again.
Tom Babbin wrote:
The problem is that proto::eval() takes its first argument by non-const reference. The temporary expression returned by pow1 doesn't bind to it as it's defined in the users' guide. Adding a const-qualification to the return type solves the problem.
I'll update the docs for 1.41. Thanks for the report.
Hi, Eric,
Thanks for the quick response. Adding a const does fix the problem. However, I am relatively new to meta programming. How come a const expression binds to the first argument of eval, while a non-const does not?
Consider this: template<class T> void foo(T &) {} struct S {}; S rvalue() { return S(); } S const const_rvalue() { return S(); } Now the following invocation fails: foo( rvalue() ); // error, non-const rvalue cannot // bind to an lvalue reference But the following invocation succeeds: foo( const_rvalue() ); // OK The reason is because in the second invocation, the template argument T is deduced to be "B const", and an rvalue can bind to a const lvalue reference. In the first invocation, T is deduced to "B" and an rvalue cannot bind to a non-const lvalue reference. HTH, -- Eric Niebler BoostPro Computing http://www.boostpro.com
Eric Niebler
The reason is because in the second invocation, the template argument T is deduced to be "B const", and an rvalue can bind to a const lvalue reference. In the first invocation, T is deduced to "B" and an rvalue cannot bind to a non-const lvalue reference.
HTH,
Thanks again, Eric. This is really helpful.
participants (2)
-
Eric Niebler
-
Tom Babbin