Như đã trình bày ở cplusplus.com, std::forward
có hai chữ ký:Tại sao có hai chữ ký của 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;
Việc sử dụng điển hình của std::forward
là để bảo tồn rvalueness trong khi đi qua các đối số cho các chức năng khác. Hãy minh họa điều này với một ví dụ:
void overloaded(int &) { std::cout << "lvalue"; }
void overloaded(int &&) { std::cout << "rvalue"; }
template <typename T>
void fwd(T && t)
{
overloaded(std::forward<T>(t));
}
Khi chúng ta gọi là fwd(0)
, T
deduces để int
(t
đã gõ int &&
). Sau đó, chúng tôi gọi số std::forward<int>(t)
. Kết quả của cuộc gọi đó là biểu thức của loại int &&
do đó, phiên bản thứ hai của chức năng overloaded
được chọn và chương trình in "rvalue" cho đầu ra tiêu chuẩn.
Khi chúng ta gọi là fwd(i)
(trong đó i là một số int biến), T
deduces để int&
(t
có kiểu int &
). Sau đó, chúng tôi gọi số std::forward<int&>(t)
. Kết quả của cuộc gọi đó (sau khi áp dụng quy tắc thu gọn tham chiếu) là biểu thức của loại int &
do đó phiên bản đầu tiên của chức năng overloaded
được chọn và chương trình in "lvalue" vào đầu ra tiêu chuẩn.
Trong cả hai trường hợp này, chúng tôi sử dụng quá tải đầu tiên của std::forward
(số chụp typename remove_reference<T>::type& arg
). Đó là bởi vì ngay cả khi loại t
là int &&
nó liên kết với tham chiếu lvalue (vì biến được đặt tên kiểu "tham chiếu rvalue cho một cái gì đó" là chính nó lvalue và lvalues không thể liên kết với tham chiếu rvalue).
Câu hỏi 1:
rằng tình trạng quá tải thứ hai của std::forward
là cái gì? Bạn có thể nghĩ ra một số ví dụ thực tế, sử dụng quá tải tham gia arg
theo tham chiếu rvalue?
Câu hỏi 2:
cplusplus.com nói:
Both signatures return the same as:
static_cast<decltype(arg)&&>(arg)
Tôi có vấn đề với điều đó, là tôi khá chắc chắn rằng nó là sai. Khi chúng tôi cố gắng trả lại điều này từ quá tải đầu tiên của std::forward
, chúng tôi sẽ gặp lỗi biên dịch.
Khi fwd
được gọi là int
rvalue, nó gọi quá tải đầu tiên là std::forward
với T = int
. Sau đó, decltype(arg)
sẽ trở thành int&
để static_cast<decltype(arg)&&>(arg)
sẽ thu gọn thành static_cast<int&>(arg)
. Tuy nhiên, kiểu trả về là int &&
và chúng tôi nhận được lỗi biên dịch:
cannot bind ‘std::remove_reference<int>::type {aka int}’ lvalue to ‘int&&’
Cả hai phiên bản quá tải của std::forward
nên trở static_cast<T&&>(arg)
. Tôi có đúng không?
Bạn có nghĩ rằng trích dẫn từ cplusplus.com là nhầm lẫn không?
Xem http://stackoverflow.com/questions/38344332/why-does-stdforward-have-two-overloads để có câu trả lời cho câu hỏi đầu tiên. – TartanLlama
@TartanLlama Cái đó có một bó 'const' và' const_cast' được rải trong suốt tho. – Yakk
'cplusplus.com' là NOT' cppreference'. 'cppreference.com' là' cppreference'. Biết sự khác biệt. – Nawaz