Perfect forwarding — pass arguments to another function preserving their value category (lvalue/rvalue) and cv-qualifiers.
1template<typename T>2void wrapper(T&& arg) {3 // Forward arg with its original value category4 target(std::forward<T>(arg));5}67void target(int& val) { std::cout << "lvalue\n"; }8void target(int&& val) { std::cout << "rvalue\n"; }910int x = 10;11wrapper(x); // Calls target(int&) — lvalue12wrapper(10); // Calls target(int&&) — rvalue13wrapper(std::move(x)); // Calls target(int&&) — rvalue
Why std::forward and not std::move: