
I've attached a sketch implementation of the idea for simple functions. It doesn't deal with function-templates yet, but might still be interesting. The tar contains two sample programs: 'or_test.cpp' is an overload-resolution test, and 'string_cat.cpp' is a small (and pretty contrived :) benchmark of std::string's operator+ against a rvalue-aware version of it, operator&. Both programs should just compile and run, no need to link against anything unusual. As far as the implementation goes, the interesting stuff are in 'move/move.hpp'. It's quite unparsable, however, as much of the code is burried under heaps of PP junk. Below is a brief description of the additions. Don't get too picky about the macro syntax, I'm sure it can be improved. Any comments are welcome. The main addition is the BOOST_MOVE_FUNCTION macro. It has the form: BOOST_MOVE_FUNCTION(return_type, name, params) If 'return_type' contains any commas, or begins with a double-colon, it should be wrapped in parantheses. 'name' should be a simple identifier (that is, not an operator), and 'params' is a PP sequence of elements of the form: kind (type) name, where 'kind' is either nothing for simple parameters (i.e., an int), 'lv' for lvalue-refs, 'const' for const-lvalue-refs, or 'rv' for rvalue-refs. 'type' is the type of the parameter, possibly containing commas, and 'name' is it's name. There's no support for default arguments ATM: BOOST_MOVE_FUNCTION(void, f, ((int) x)) === void f(int x) BOOST_MOVE_FUNCTION(void, f, (lv (int) x)) === void f(int& x) BOOST_MOVE_FUNCTION(void, f, (const (int) x)) === void f(const int& x) BOOST_MOVE_FUNCTION(void, f, (rv (int) x)) === void f(int&& x) The main thing to keep in mind is that overload sets defined using BOOST_MOVE_FUNCTION need to be "complete": For every overload that takes a 'const' parameter, there has to be an equivalent overload with the same parameter as an 'rv', and vice-versa. 'lv' overloads are optional. If you want to take a parameter by ref-to-const without having to write a rv-ref overload, specify it as a simple parameter (that is, '(const int&) x' instead of 'const (int) x'). BOOST_MOVE_FUNCTION has additional forms that take up to 3 extra parameters, and are distinguished by their suffixes: N for nickname, P for prefix and S for suffix. Any combination of suffixes is possible but they have to be in the above order. The placement of the extra parameters with respect to the rest is the same for all forms, so I'm just going to list the most general one: BOOST_MOVE_FUNCTION_NPS(nickname, prefix, return_type, name, params, suffix) 'nickname' should be used when name is not an identifier (that is, an operator), and should itself be a simple identifier. Functions with different names should have different nicknames. Furthermore, the forms of BOOST_MOVE_FUNCTION that don't take a nickname internally use the function's name as the nickname, so it should be unique with respect to names of these functions as well. If 'name' contains commas (operator ,) it should be wrapped in parantheses. 'prefix' is added before the return type (i.e. inline, static, etc...). The only requirement is that if 'inline' is one of the specifiers in 'prefix', it should come first. 'suffix' comes after the parameters list (i.e. const, throw(), etc...). BOOST_MOVE_FUNCTION should only be used for free-functions. Member-functions should use BOOST_MOVE_MEMBER_FUNCTION, which is otherwise identical. Constructors are not supported ATM. For separate declaration and definition, use BOOST_MOVE_FUNCTION (or MEMBER_FUNCTION) for the declaration, followed by a semi-colon. Then use BOOST_MOVE_FUNCTION_DEFINITION for the definition, which has the same form of BOOST_MOVE_FUNCTION. BOOST_MOVE_MEMBER_FUNCTION_DEFINITION takes an aditional 'class_name' parameter (possibly wrapped in parantheses) before 'name'. BOOST_MOVE_FUNCTION, as a declaration, can appear at most once for each overload, even at namespace scope. User-defined conversions work as expected. Furthermore, they're dispatched to the correct overload (to the lvalue overload if they yield a lvalue, and to the rvalue one if they yield a rvalue). However, the ability to correctly determine the l/r-valueness of the result of a user-defined conversion requires the compiler to be conformant enough. In case the compiler isn't capable of that, all user-defined conversions are considered to yield lvalues.