C++11 (and C++14) introduces additional language constructs and improvements that target generic programming. These include features such as;
Here is a practical example.
struct concat {
std::vector state;
std::vector const& operator()(int x)&{
state.push_back(x);
return state;
}
std::vector operator()(int x)&&{
state.push_back(x);
return std::move(state);
}
std::vector const& operator()()&{ return state; }
std::vector operator()()&&{ return std::move(state); }
};
This function object takes an x
, and concatenates it to an internal std::vector
. It then returns that std::vector
.
If evaluated in an rvalue context it move
s to a temporary, otherwise it returns a const&
to the internal vector.
Now we call apply
:
auto result = apply( concat{}, std::make_tuple(2) );
because we carefully forwarded our function object, only 1 std::vector
buffer is allocated. It is simply moved out to result
.
Without the careful forwarding, we end up creating an internal std::vector
, and we copy it to result
, then discard the internal std::vector
.
Because the operator()&&
knows that the function object should be treated as a rvalue about to be destroyed, it can rip the guts out of the function object while doing its operation. The operator()&
cannot do this.
Careful use of perfect forwarding of function objects enables this optimization.
Note, however, that there is very little use of this technique "in the wild" at this point. Rvalue qualified overloading is obscure, and doing so to operator()
moreso.
I could easily see future versions of C++ automatically using the rvalue state of a lambda to implicitly move
its captured-by-value data in certain contexts, however.