What is the best way to bind an rvalue reference to either a given object or a temporary copy of it?
A &&var_or_dummy = modify? static_cast<A&&>( my_A )
: static_cast<A&&>( static_cast<A>( my_A ) );
(This code doesn't work on my recent GCC 4.6… I recall it working before, but now it always returns a copy.)
On the first line, the static_cast
transforms my_A
from an lvalue to an xvalue. (C++0x §5.2.9/1-3) The inner static_cast
on the second line performs lvalue-to-rvalue conversion, and the outer one obtains an xvalue from this prvalue.
This appears to be supported because the named reference is conditionally bound to the temporary per §12.2/5. The same trick works the same way in C++03 with a const
reference.
I can also write the same thing less verbosely:
A &&var_or_dummy = modify? std::move( my_A )
: static_cast<A&&>( A( my_A ) );
Now it's much shorter. The first abbreviation is questionable: move
is supposed to signal that something is happening to the object, not a mere lvalue-to-xvalue-to-lvalue shuffle. Confusingly, move
cannot be used after the :
because the function call would interrupt the temporary-to-reference binding. The syntax A(my_A)
is perhaps clearer than the static_cast
, but it's technically equivalent to a C-style cast.
I can also go all the way and write it entirely in C-style casts:
A &&var_or_dummy = modify? (A&&)( my_A ) : (A&&)( A( my_A ) );
After all, if this is going to be an idiom, it must be convenient, and static_cast
isn't really protecting me from anything anyway — the real danger is failing to bind directly to my_A
in the true
case.
On the other hand, this easily gets dominated by the typename repeated three times. If A
were replaced with a big, ugly template-id, I'd really want a real shortcut.
(Note that V
is evaluated only once despite appearing five times:)
#define VAR_OR_DUMMY( C, V ) ( (C)? \
static_cast< typename std::remove_reference< decltype(V) >::type && >( V ) \
: static_cast< typename std::remove_reference< decltype(V) >::type && > ( \
static_cast< typename std::remove_reference< decltype(V) >::type >( V ) ) )
Hackish as macros are, I think that's the best alternative of the bunch. It's a bit dangerous because it returns an xvalue, so it shouldn't be used outside reference initialization.
There must be something I haven't thought of… suggestions?