In the MSVC STL, the implementation of std::apply
is as follows:
template <class _Callable, _Tuple_like _Tuple, size_t... _Indices>
constexpr decltype(auto) _Apply_impl(_Callable&& _Obj, _Tuple&& _Tpl, index_sequence<_Indices...>) noexcept(/* [...] */) {
return _STD invoke(_STD forward<_Callable>(_Obj), _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...);
}
In the expression _STD get<_Indices>(_STD forward<_Tuple>(_Tpl))...
, std::get
is called the same number of times as the length of the tuple. However, with each invocation of std::get
, there is a corresponding invocation of std::forward.
When forwarding an rvalue, std::forward
is equivalent to std::move
, implying multiple calls to std::move
for the _Tpl
object. This seems to be potentially invalid. Could someone help explain my concern?
I've tried searching through various resources, but I couldn't find the answer I was looking for. Starting from the definition also hasn't convinced me.
std::move
, it doesn't really do anything, all it does is converting the argument to an rvalue reference. Why would it be problematic with many move calls? Why would it be invalid? – Avram