[phoenix] adding const to member_variable bind

Hi there, the following code doesn't compile since I'm iterating over a constant vector of points. struct point { double _prob; double _x; }; void test( const std::vector< point >& d ) { double sum_prob = std::accumulate( d.begin() , d.end() , 0.0 , arg1 + bind( &point::_prob, arg2 ) ); } int _tmain(int argc, _TCHAR* argv[]) { std::vector< point > d; test( d ); return 0; } My question is how can I convert or cast the "&point::_prob" into a const reference? I tried several ways but they all don't work. The only thing that worked was to add const getter function in my point structure. Like this: struct point { point( double prob, double x ) : _prob( prob ), _x( x ) {} const double& prob() const { return _prob; } double _prob; double _x; }; Thanks, Christian

AMDG Christian Henning wrote:
My question is how can I convert or cast the "&point::_prob" into a const reference?
static_cast<const double point::*>(&point::_prob) should work, but really, this is a bug in phoenix. Patch against the trunk attached. In Christ, Steven Watanabe

Steven Watanabe wrote:
Thanks, Steven. Please feel free to apply the patch. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

AMDG Steven Watanabe wrote:
I'm stuck here: struct x { int m; }; // instantiates member_variable::result<x>, // but calls member_variable::operator()(const x&). bind(&x::m, x())(); // instantiates member_variable::result<x> because // top level references are stripped. bind(&x::m, ref(x)); There is no way for result to distinguish between these cases, even though they are different. In Christ, Steven Watanabe

Steven Watanabe wrote:
Out of curiosity, how does Boost.Bind and Lambda.Bind behave in this regard? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

AMDG Joel de Guzman wrote:
It looks like: a) bind always constifies the return type of a pointer to a data member. b) lambda does not strip references in its return type deduction. #include <boost/spirit/home/phoenix/bind.hpp> #include <boost/spirit/home/phoenix/core.hpp> #include <boost/bind.hpp> #include <boost/ref.hpp> #include <boost/lambda/bind.hpp> struct x { int m; }; void boost_bind() { using namespace boost; x x_ = {0}; bind(&x::m, x_)(); bind(&x::m, ref(x_))() = 1; // does not compile--returns const int& bind(&x::m, cref(x_))(); } void boost_lambda() { namespace lambda = boost::lambda; x x_ = {0}; lambda::bind(&x::m, x_)(); lambda::bind(&x::m, lambda::var(x_))() = 1; lambda::bind(&x::m, lambda::var(static_cast<const x&>(x_)))(); } void boost_phoenix() { namespace phoenix = boost::phoenix; x x_ = {0}; phoenix::bind(&x::m, phoenix::val(x_))(); // does not compile phoenix::bind(&x::m, phoenix::ref(x_))() = 1; phoenix::bind(&x::m, phoenix::cref(x_))(); // does not compile } In Christ, Steven Watanabe

Steven Watanabe wrote:
[...]
The third is ok with your patch. Anyway, ok, this is a bug due to, as you noticed, stripping of the top level reference. Seems it's a limitation of the old result-type scheme. I think it can only be fixed when we move to the result_of protocol which respects the references. Anyway, I added your test (which fails the val(x) test and your patch (which allows the cref(x) test). I'll keep the failing val(x) test to remind me to fix this bug. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

Steven Watanabe wrote:
Cool. Feel free to add these tests. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
participants (3)
-
Christian Henning
-
Joel de Guzman
-
Steven Watanabe