On 7/14/2014 12:56 AM, Andrey Semashev wrote:
On Sunday 13 July 2014 17:04:09 Eric Niebler wrote:
On 7/13/2014 2:48 AM, Peter Dimov wrote:
Andrey Semashev wrote:
Perhaps Eric could provide more context on why Boost.Proto needs recursive reference wrappers? Frankly, the requirement looks strange to me.
Generic code that does
boost::reference_wrapper<T> r = boost::ref( t );
is broken when t is a reference_wrapper.
Right. That's exactly what I argued in committee. Doug Gregor was the only person I was able to convince. C'est la vie. It's also why Proto broke.
Proto doesn't *need* the old behavior, strictly speaking. But the part of proto that builds expressions, proto::make_expr, was designed around the old semantics. See http://bit.ly/1oUbgZr. proto::result_of::make_expr is a metafunction for computing the result of the proto::make_expr function. It interprets reference types as the types of things to be held by reference, and non-reference types to be held by value. When calling proto::make_expr at run-time, each argument to be held by reference must be wrapped in boost::ref. It uses the generic-friendly invariant of boost::ref that Peter references above.
I've already hacked Proto and it's tests to accommodate the change, and the tests are turning green again, so it's not a huge deal. But end user code will have to change. Xpressive didn't break, and it looks like Spirit didn't break, so the scope of the breakage might be small. Hard to say.
Thank you Eric.
Am I right that the user's code that uses proto::result_of::make_expr (or any other Proto metafunction for result type computation) won't be broken?
Define "broken". proto::result_of::make_expr will now compute a different type than for the previous release. So anybody who is depending on the exact type will be broken. This is probably not a lot of people.
I'm omitting for now the possibility that the user's code could use the reference wrapper like in the Peter's code sample. From your changes to Proto tests I could not see what kind of changes would be required on the user's side.
These are the changes: https://github.com/boostorg/proto/commit/d9a4fc37c2b99a08648a5245ce637e60d4b... The changes in proto/test/mem_ptr.cpp are an example of where things get weird. If you pass a reference_wrapper<int> to boost::ref, you get a reference_wrapper<int>. But it you pass it to boost::cref, you get a reference_wrapper<int const>. This changes the type computation in yet another way, and yet another code invariant is broken. Previously, it was the case that if you have a T const &, it doesn't matter if you call boost::ref or boost::cref. Now it does, and anybody who uses boost::cref together with proto::make_expr is in for a rude surprise. The type of the returned object will not be the same as the type computed by proto::result_of::make_expr. (This is what broke the test.) -- Eric Niebler Boost.org http://www.boost.org