Andrey Semashev wrote:
Well, you might want to do something on t before invoking the common logic in foo.
I admit I invented this example just now, but I can imagine something like this in real life.
If you try to come up with plausible specifications for foo and foo1, you'll see that calling foo1 with ref() makes no sense. Passing ref() to a function typically means that the function does something (stores by value, forwards by value) unless given a reference_wrapper as an override, in which case it does something else (stores a reference, forwards by reference). That's our foo. foo1, then, explicitly wants to enable the reference behavior of foo. It itself however doesn't need to take reference_wrappers - it always treats its argument as a reference. Caller code has no need to call foo1 with ref(x). This is not part of foo1's interface - it accomplishes nothing. The fact that in so many years of boost::ref use nobody has requested this behavior should tell you something. (Unless, of course, someone has and I've forgotten about it.) It's a simple point, ref(x) gives you reference_wrapper<X>, and the collapsing behavior introduces a special case in which this isn't true. Similarly, ref(rv), where rv is an rvalue, should fail in order to not capture a dangling reference, but we are trying as a special case to make it work when rv is a reference_wrapper, a behavior that makes even less sense (even if it happened to work before - but then again, other rvalues also worked). Special cases need a justification stronger than "we are sure we can imagine cases in which this would be useful, so let's put that to a vote without even bothering to actually imagine".