Jak stwierdzono w cplusplus.com, std::forward
ma dwa podpisy:Dlaczego istnieją dwa sygnatury std :: forward?
template <class T> T&& forward (typename remove_reference<T>::type& arg) noexcept;
template <class T> T&& forward (typename remove_reference<T>::type&& arg) noexcept;
Typowe zastosowanie std::forward
jest zachowanie rvalueness przechodząc argumenty do innych funkcji. Zilustrujmy to na przykładzie:
void overloaded(int &) { std::cout << "lvalue"; }
void overloaded(int &&) { std::cout << "rvalue"; }
template <typename T>
void fwd(T && t)
{
overloaded(std::forward<T>(t));
}
Kiedy wzywamy fwd(0)
, T
wnioskuje do int
(t
ma typ int &&
). Następnie dzwonimy pod numer std::forward<int>(t)
. Wynikiem tego połączenia jest wyrażenie typu int &&
, dlatego wybrano drugą wersję funkcji overloaded
, a program wypisze "rvalue" na standardowe wyjście.
Kiedy wzywamy fwd(i)
(gdzie jest jakiś int zmienna), T
wnioskuje, do int&
(t
ma typ int &
). Następnie dzwonimy pod numer std::forward<int&>(t)
. Wynikiem tego połączenia (po zastosowaniu referencyjnych reguł zwijania) jest wyrażenie typu int &
, dlatego wybrano pierwszą wersję funkcji overloaded
, a program wypisze "lwartość" na standardowe wyjście.
W obu przypadkach używamy pierwszego przeciążenia z std::forward
(ten pobierający typename remove_reference<T>::type& arg
). Dzieje się tak, ponieważ nawet jeśli typ t
jest int &&
, wiąże on referencję lwartościową (ponieważ zmienna nazwana typu "odniesienie r wartości do czegoś" jest sama w sobie lwartością, a wartości l nie mogą wiązać się z odniesieniem do wartości r).
Pytanie 1:
Co to jest drugi przeciążenie std::forward
za? Czy możesz wymyślić jakiś praktyczny przykład, który używa przeciążenia pobierając arg
przez referencję rwartości?
Pytanie 2:
cplusplus.com mówi:
Both signatures return the same as:
static_cast<decltype(arg)&&>(arg)
Mam problem z tym, że jestem pewien, że to jest złe. Kiedy próbujemy zwrócić to od pierwszego przeciążenia std::forward
, otrzymujemy błąd kompilacji.
Kiedy fwd
nazywa się int
rvalue, wywołuje pierwszy przeciążenie std::forward
z T = int
. Następnie decltype(arg)
stanie się int&
, więczapadnie się do static_cast<int&>(arg)
. Ale typ zwracany jest int &&
i otrzymujemy błąd kompilacji:
cannot bind ‘std::remove_reference<int>::type {aka int}’ lvalue to ‘int&&’
Oba przeciążone wersje std::forward
powinien powrócić static_cast<T&&>(arg)
. Czy mam rację?
Czy uważasz, że cytat z cplusplus.com jest błędem?
Zobacz http://stackoverflow.com/questions/38344332/why-does-stdforward-hole-two-overloads dla odpowiedzi na pierwsze pytanie. – TartanLlama
@TartanLlama To, że jeden ma garść 'const' i' const_cast' skrócone przez tho. – Yakk
'cplusplus.com' to NIE' cppreference'. 'cppreference.com' to' cppreference'. Znać różnicę. – Nawaz