2

I can create a boost::phoenix::lambda that captures by value. However, trying to modify a variable captured by value produces the following error

error: read-only variable is not assignable
    BOOST_PROTO_BINARY_DEFAULT_EVAL(=, assign, make_mutable, make)

Makes sense, just capture by reference then. Capturing by reference produces the following error in clang 3.2:

error: call to 'ref' is ambiguous
    auto a = lambda(_a = ref(dv), _b = ref(i))[ _a[arg1] = _b, _a[arg1] ];
                         ^~~

/usr/include/c++/v1/__functional_base:388:1: note: candidate function [with _Tp =
      std::__1::vector<double, std::__1::allocator<double> >]
ref(_Tp& __t) _NOEXCEPT
^
/usr/local/include/boost/phoenix/core/reference.hpp:68:12: note: candidate function [with T
      = std::__1::vector<double, std::__1::allocator<double> >]
    inline ref(T & t)
           ^

In the following example I need to capture by reference in order to get code that is equivalent to the C++11 lambda. What is the correct way to capture by reference in boost::phoenix::lambda ?

Minimal example:

#include<iostream>
#include<vector>
#include<boost/phoenix/phoenix.hpp>
using namespace boost::phoenix;
using namespace boost::phoenix::placeholders;
using namespace boost::phoenix::local_names;

template<class D = void> struct A {
  A() : i(1), dv(2,2) {}
  int i; std::vector<int> dv;
  void fun() {
    //auto a = [&](int j){ dv[j] = i; return dv[j]; }; // C++11

    // boost::phoenix capture by value works, does not modify dv.
    //auto a = lambda(_a = val(dv), _b = val(i))[ _a[arg1] + _b];

    // boost::phoenix capture by value: modifying the vector does not work.
    auto a = lambda(_a = val(dv), _b = val(i))[ _a[arg1] = _b, _a[arg1] ];

    // boost::phoenix capture by reference: doesn't work.
    auto a = lambda(_a = ref(dv), _b = ref(i))[ _a[arg1] = _b, _a[arg1] ];
    for(size_t t = 0; t != dv.size(); ++t) {
      std::cout << "vt: " << a()(t) << std::endl;
    }   
  }
};

int main() {
  A<void> a;
  a.fun();
  return 0;
}

Update 1: Removed using namespace std; (suggested by Xeo in the comments).

ildjarn
  • 62,044
  • 9
  • 127
  • 211
gnzlbg
  • 7,135
  • 5
  • 53
  • 106
  • 6
    Stop ab `using namespace std;` right this moment, and your problem should go away. There's a `std::ref` from ``, if that header is somehow indirectly included. Just qualify your names. – Xeo Feb 20 '13 at 13:46
  • @Xeo I just tried without the `using namespace std` directive and I still get an ambigous call of ref. Gonna update the question to remove that using directive. Indeed, even without the using, the name ref is colliding with ref from `std::functional`. Thanks! – gnzlbg Feb 20 '13 at 13:48
  • 2
    Well, that's thanks to ADL, because `dv`'s type resides inside `namespace std`. As I said, qualify your names. *All* of them. `namespace phx = boost::phoenix; ... phx::_a = phx::ref(dv)` etc. – Xeo Feb 20 '13 at 13:53

0 Answers0