Perfect forwarding


template<typename T, typename Arg>
shared_ptr<T> factory(Arg arg)
{
  return shared_ptr<T>(new T(arg));
}


Unfortunately, this will call T(arg) by value.
A half-good solution is passing arg by reference:


template<typename T, typename Arg>
shared_ptr<T> factory(Arg& arg)
{
  return shared_ptr<T>(new T(arg));
}


But this does not work for rvalue parameters:

factory<X>(f());        // error if f() returns by value
factory<X>(42);         // error


So we can add an overloaded factory function:

template<typename T, typename Arg>
shared_ptr<T> factory(const Arg& arg)
{
  return shared_ptr<T>(new T(arg));
}


Here is the issue:

-- If factory has many arguments, we have to provide all combinations
   of const and non-const references.

-- arg parameter inside factory() is an lvalue --> no move semantics



Reference collapsing:


In pre-C++11 no way to set a reference to a reference: A& & is a compile error
In C++11 we have "reference collapsing" rule:


  A& &   --> A&
  A& &&  --> A&
  A&& &  --> A&
  A&& && --> A&&


template <typename T>
void f(T&&);            // special template argument deduction rule

- If f() called on "lvalue of A"  T --> A&     argument type --> A&
- If f() called on "rvalue of A"  T --> A      argument type --> A



template<typename T, typename Arg>
shared_ptr<T> factory(Arg&& arg)
{
  return shared_ptr<T>(new T(std::forward<Arg>(arg)));
}
template<class S>
S&& forward(typename remove_reference<S>::type& a) noexcept
{
  return static_cast<S&&>(a);
}




Examples:

X x;
factory<A>(x);         Arg --> X&

X& && forward(remove_reference<X&>::type& a) noexcept
{
  return static_cast<X& &&>(a);
}
shared_ptr<A> factory(X& && arg)
{
  return shared_ptr<A>(new A(std::forward<X&>(arg)));
}

which becomes:

shared_ptr<A> factory(X& arg)
{
  return shared_ptr<A>(new A(std::forward<X&>(arg)));
}
X& std::forward(X& a)
{
  return static_cast<X&>(a);
}


X foo();
factory<A>(foo());      Arg --> X

shared_ptr<A> factory(X&& arg)
{
  return shared_ptr<A>(new A(std::forward<X>(arg)));
}

X&& forward(X& a) noexcept
{
  return static_cast<X&&>(a);
}


std::forward --> keeps move semantic

std::remove_reference<S>::type&  == S&




template<class T>
typename remove_reference<T>::type&&
std::move(T&& a) noexcept
{
  typedef typename remove_reference<T>::type&& RvalRef;
  return static_cast<RvalRef>(a);
}



std::move(x)   <===>   static_cast<X&&>(x)