
On Fri, Jan 13, 2012 at 1:04 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
Here's my position: - Ideally, client code written for both C++11 and C++03 should not have "ugly" workarounds for C++03 deficiencies, and that's basically what wrapping all function parameters in some BOOST_MOVE macro (or similar) would be, a workaround.
No argument here.
- If you really want to guarantee C++11-level performance in C++03 and the interface can't otherwise guarantee this, and this necessitates some kind of workaround, then one workaround (wrapping in a BOOST_MOVE macro) is just about as bad as another (storing a temporary and explicitly moving).
Allow me to disagree. I think one altenative is way better than the other, as it doesn't force you to spread your call expression over multiple statements, which is, aside from being obscure (BOOST_MOVE is ugly, but pretty straight-forward), is not applicable in some contexts (i,e, initializer lists).
In any case, even if we did end up agreeing that wrapping function parameters in a BOOST_MOVE macro was desireable, this doesn't entirely preclude BOOST_FWD_REF( T ) from expanding to T const &;
That's right, these are two separate things. moveable
temporaries would still be moved. The loss is that const-ness of lvalues is not preserved, but that isn't a common case.
Not too common, but far from being a corner case either.
[...]
Interesting. Could you provide a reference or an example?
Here's the idea. In C++11, you can just get away with [...]
Thanks for expanding. That's a clever trick :). I thought you were taking about something a bit different though, as this method doesn't scale to functions taking more than a single parameter (it's theoretically possible, but not practical), so it's not a general solution to forwarding. Btw, if that's all you're trying to do, won't something like this be a lot simpler? #include <iostream> #include <boost/type_traits/is_const.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/utility/enable_if.hpp> template <typename T> struct movable {}; struct i_can_move : movable<i_can_move> {}; template <typename T> void what_is(T&) { if(!boost::is_const<T>::value) std::cout << "modifiable lvalue" << std::endl; else std::cout << "const lvalue" << std::endl; } template <typename T> typename boost::disable_if< boost::is_convertible<T, movable<T> >
::type what_is(const T&) { std::cout << "non-movable const-lvalue " "or rvalue" << std::endl; }
template <typename T> void what_is(const movable<T>&) { std::cout << "rvalue" << std::endl; // No indirect call, and we get to know what T is } int main() { { i_can_move x; const i_can_move y = x; what_is(x); what_is(y); what_is(i_can_move()); } std::cout << std::endl; { int x; const int y = 123; what_is(x); what_is(y); what_is(123); } }
[...]
So, it seems that you're already using the same thing I suggest...
Well, any function using BOOST_FWD2_REF in its parameter list is only passed parameters that are lvalues or the result of a boost::forward. So, I guess I'm using the same thing, but it doesn't sound like it's in the same context...?
But since we only have one BOOST_FWD_REF, I belive it should be applicable to any context (and you belive that it should be "optimized" for the most common one, point is clear, let's not open that again ;) )