Answer the question
In order to leave comments, you need to log in
Why would std::forward have two signatures and explicitly state the type?
In the standard, std::forward has two signatures (for lvalue and rvalue) and requires the user to explicitly specify the type:
template <class T> T&& forward (typename remove_reference<T>::type& arg) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& arg) noexcept;
static_cast
Link folding will work and the result will be equivalent to the standard function .template <typename T>
decltype(auto) my_forward(T&& arg) // universal reference (can be rvalue- or lvalue-reference)
{
return static_cast<T&&>(arg);
// T&& can be expanded to:
// Foo& && - gives us Foo&
// const Foo& && - give us const Foo&
// Foo && - gives us Foo&&
// const Foo && - gives us const Foo&&
}
template <typename T>
func (T&& foo1, T&& foo2)
{
f(std::forward<Foo>(foo1), my_forward(foo2));
}
Answer the question
In order to leave comments, you need to log in
I think this article will answer your questions.
If the most pointwise, then this is the section "Implementing the ideal transfer using std::forward" and a quote in it.
Another point to note is the use of std::remove_reference. In fact, forward can be implemented without using this function. Reference compression will do all the work, so using std::remove_reference is redundant for this. However, this function allows you to infer T& t in situations where this type cannot be inferred (according to the C++ standard, 14.8.2.5), so you must explicitly specify template parameters when calling std::forward.
Attempt No. 2, the first one was nonsense:
The main problem is that inside the method all parameters are of the l-value type. That is, the parameter modifier && is only a requirement that the calling code pass r-value in place of this argument (and for templates it doesn’t even require this, thanks to link gluing). And if so, then your my_forward method will remake it to return l-value references in general for all arguments.
Hence the need to explicitly specify the type of the argument is taken - so that it is the derived type that is used, and not l-value for this type. Well, why 2 specializations: if you explicitly specify the type of the argument and explicitly specialize the function with some r-value, then my_forward will expect strictly r-value, and the parameter value that is l-value will not fit there.
To explain my thoughts, code
#include <iostream>
template<typename T>
decltype(auto) my_forward(T&& arg)
{
return static_cast<T&&>(arg);
}
template <typename T, typename K>
void forward(T&& t, K&& k)
{
std::cout << std::is_same<int&&, decltype(my_forward(t))>::value << std::endl;
std::cout << std::is_same<int&, decltype(my_forward(k))>::value << std::endl;
std::cout << std::is_same<int&&, decltype(std::forward<T>(t))>::value << std::endl;
std::cout << std::is_same<int&, decltype(std::forward<K>(t))>::value << std::endl;
}
int main()
{
int lval = 10;
forward(10, lval);
return 0;
}
std::forward is for use in templates; without a template, you can use the good old std::move.
In addition, std::forward is set up in such a way that the template parameter must be specified explicitly.
The task of std::forward is to pass further a simple or temporary reference, depending on which reference the user passes.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question