
On Mon, Apr 11, 2011 at 5:46 AM, Eric Niebler <eric@boostpro.com> wrote:
On 4/10/2011 9:22 PM, Jeffrey Lee Hellrung, Jr. wrote:
I have a follow-up to my original message regarding a typeless emulated rvalue reference. I was disappointed in the lack of feedback (other than Dave) on the original message, which might mean that those who took the time to parse the message didn't think it was worth pursuing;
Not at all. I am very interested in improved move emulation in C++03. Speaking solely from myself, I just don't have the time to do the technical investigation that it would take to respond intelligently to your mail. I expect some others are in the same position. Please don't be discouraged!
Totally understandable. Perhaps a short summary will be useful, with full details provided in [1]. I'm assuming familiarity with C++0x rvalue references. For those unfamiliar, I recommend the "RValue References: Moving Forward" sequence of articles by Dave Abrahams, e.g., [2]. I also recommend familiarity with Boost.Move [3,4], which basically provides the current state-of-the-art move and rvalue reference emulation within C++03. I propose to supplement Boost.Move to very closely approximate perfect forwarding. To be a little bit more specific... One of the problems that rvalue references solves is the forwarding problem [5]. To the best of my knowledge (until now!), the best approximation to generic forwarding in C++03 turns rvalues into lvalues ([5], indeed, says as much), but preserving the rvalueness of a function argument is important to identify when one can safely move from the argument. I have devised a technique (let's call it the "typeless emulated rvalue reference (TERR) technique") that, when combined with the existing Boost.Move emulation framework, can actually preserve rvalueness for *arbitrary* (move-emulation-enabled) types. To get an idea of what such a forwarding overload set might look like, let's modify the first example, unary_function_wrapper, from [5] to use a TERR to achieve perfect forwarding: template< class F > struct unary_function_wrapper { unary_function_wrapper(F f) : m_f(f) { } template< class T > void operator()(T& x) { m_f(x); } // genrv< Visitor > is a TERR typedef genrv< unary_function_wrapper > genrv_type; template< class T > typename boost::disable_if< boost::is_convertible< T&, genrv_type >
::type operator()(T const & x) { m_f(x); }
void operator()(genrv_type x) { x(*this); } private: F m_f; }; Now, if X is *any* move-emulation-enabled class, unary_function_wrapper<F> will capture X-rvalues by emulated-rvalue-reference rv<X>& and forward this onto the wrapper function object m_f, thus preserving rvalueness. Of course, it's far from obvious how that happens, exactly, just given the above code, so for those interested in *how* that's achieved, I again refer you to [1]. Hopefully this summary helps determine whether one should investigate [1] in detail or not. - Jeff [1] http://thread.gmane.org/gmane.comp.lib.boost.devel/217478/focus=217772 [2] http://cpp-next.com/archive/2009/09/move-it-with-rvalue-references/ [3] http://igaztanaga.drivehq.com/libs/move/doc/html/index.html [4] http://svn.boost.org/svn/boost/sandbox/move/ [5] http://cpp-next.com/archive/2009/12/onward-forward/