[lambda] Wrong return type for dereference for pointer to member

Lambda's return type deduction for a pointer to member action doesn't honour the object constness. Regardless of the object constness, the return type is always a non const reference to the member type. The following code illustrates the issue: struct aux { aux() : b(1) {} int b; }; struct aux_ptr { aux_ptr(aux *ptr=NULL) : m_ptr(ptr) {} ~aux_ptr() { delete m_ptr; } template <class R> R &operator->*(R aux::*m) { return m_ptr->*m; } template <class R> const R &operator->*(R aux::*m) const { return m_ptr->*m; } private: aux *m_ptr; }; int main() { // This compiles nicely aux_ptr ptr(new aux()); cout << (_1->*&aux::b)(ptr) << endl; // This fails to compile. const aux_ptr cptr(new aux()); cout << (_1->*&aux::b)(cptr) << endl; return 0; } The second part should compile if other_action<member_pointer_action> honoured _1's constness. Thanks, Rodolfo Lima

The second part should compile if other_action<member_pointer_action> honoured _1's constness.
Adding this specialization makes the code compile: namespace boost { namespace lambda { template <class R, class T, class U> class return_type_2<other_action<member_pointer_action>, const T, R U::* const> { public: typedef const R &type; }; }} So, I think that the same return deduction made in struct member_pointer_action_helper<true, false> should be done in struct member_pointer_action_helper<false, false>, which is the specialization called for the code in the previous message. What do you think? Regards, Rodolfo Lima.

On Nov 29, 2006, at 3:43 PM, Rodolfo Lima wrote:
Lambda's return type deduction for a pointer to member action doesn't honour the object constness. Regardless of the object constness, the return type is always a non const reference to the member type.
The following code illustrates the issue:
struct aux { aux() : b(1) {} int b; };
struct aux_ptr { aux_ptr(aux *ptr=NULL) : m_ptr(ptr) {} ~aux_ptr() { delete m_ptr; }
template <class R> R &operator->*(R aux::*m) { return m_ptr->*m; } template <class R> const R &operator->*(R aux::*m) const { return m_ptr->*m; } private: aux *m_ptr; };
int main() { // This compiles nicely aux_ptr ptr(new aux()); cout << (_1->*&aux::b)(ptr) << endl;
Hmm... why does this even compile? strange.
// This fails to compile. const aux_ptr cptr(new aux()); cout << (_1->*&aux::b)(cptr) << endl; return 0; }
Both versions above are delayed calls to user-defined operator->* and the in general the library won't guess what the result type should be. In the latter case the lib would have to guess that constness of aux_ptr means that R should be constified in the return, which is too much guess work. This should work: std::cout << ret<const int&>(_1->*&aux::b)(cptr) << std::endl; Cheers, Jaakko
The second part should compile if other_action<member_pointer_action> honoured _1's constness.
Thanks, Rodolfo Lima
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/ listinfo.cgi/boost

// This compiles nicely aux_ptr ptr(new aux()); cout << (_1->*&aux::b)(ptr) << endl;
Hmm... why does this even compile? strange.
I see, after looking at the code I don't see a specialization for plain_return_type_2<other_action<member_pointer_action> >. FYI I'm using g++ 4.1.1.
Both versions above are delayed calls to user-defined operator->* and the in general the library won't guess what the result type should be. In the latter case the lib would have to guess that constness of aux_ptr means that R should be constified in the return, which is too much guess work.
Maybe lambda could support what I think is a common scenario, i.e., smart pointer-like objects. The worst think that may happen is, IMO, a compilation failure. Regards, Rodolfo Lima.
participants (2)
-
Jaakko Järvi
-
Rodolfo Lima