Search code examples
c++11move-semanticsmake-shared

std::make_shared and std::forward — what's the point?


I'm trying to understand why std::make_shared is declared/implemented the way it is:

template<class _Tp, class ..._Args>
inline _LIBCPP_INLINE_VISIBILITY
typename enable_if
<
    !is_array<_Tp>::value,
    shared_ptr<_Tp>
>::type
make_shared(_Args&& ...__args)
{
    return shared_ptr<_Tp>::make_shared(_VSTD::forward<_Args>(__args)...);
}

What I'm curious about is:

  • Why does make_shared accept only rvalue-references? Why there's no overload for reference-to-constant (i.e., const _Args &)?
  • What's the point of _VSTD::forward call?

Good explanation or good hyperlink will both be highly appreciated.


Solution

  • Why does make_shared accept only rvalue-references? Why there's no overload for reference-to-constant (i.e., const _Args &)?

    This is a universal reference that binds both to r-values and l-values. For r-values the deduced type is T, for l-values it is T&.

    What's the point of _VSTD::forward call?

    When a temporary is bound to an r-value reference, that reference (the name) is not r-value any more. You need to be able to restore the original value category of the value and this is what std::forward<> is for: to forward the r-value arguments as r-values and l-value arguments as l-values.

    Essentially std::forward applies && to T or T&. When && is applied to

    • T it becomes T&& - the r-value reference, and
    • T& becomes T&&&, which is again T&.