Tôi thiết lập một trường hợp thử nghiệm để tìm hiểu về chuyển tiếp hoàn hảo.C++ 11: sự tinh tế của std :: forward: Danh tính có thực sự cần thiết không?
std::string inner(const std::string& str) {
return "const std::string&";
}
std::string inner(std::string& str) {
return "std::string&";
}
std::string inner(const std::string&& str) {
return "const std::string&&";
}
std::string inner(std::string&& str) {
return "std::string&&";
}
template <typename T> void outer(T&& t) {
std::cout << "t: " << t << std::endl;
std::cout << "perfect forward: " << inner(std::forward<T>(t)) << std::endl;
std::cout << std::endl;
}
void PerfectForwarding()
{
outer("literal");
outer(lvalue);
outer(constlvalue);
outer(rvalue());
outer(constrvalue());
}
std::forward
hoạt động như mong đợi. Các hành vi thú vị xuất hiện khi tôi thực hiện chức năng chuyển tiếp của riêng tôi mà không sắc:
template <typename T> T&& MyForward(T& t)
{
return ((T&&)t);
}
Thay std::forward
với MyForward
ở bên ngoài cung cấp cho kết quả chính xác cùng! Hành vi này đặt ra câu hỏi tại sao danh tính được sử dụng?
Compiler VS2010
Cập nhật 1: Trong tài liệu tham khảo để ngăn chặn loại trừ
AFAIK, các quy tắc loại trừ đặc biệt chỉ được kích hoạt trên T & &. Lưu ý định nghĩa về phía trước, forward(typename identity<T>::type& t)
. Loại đối số chỉ có một &. Trong thực tế, sau khi tôi thay đổi MyForward để sử dụng danh tính, và bỏ ra (T & &) truyền, ví dụ không biên dịch. Trên bề mặt, việc đúc từ lvalue đến rvalue dường như làm cho công việc tiến lên.
Cập nhật 2: được thử nghiệm trên ideone.com với GCC 4.5, cùng một hành vi.
Bạn có ý nghĩa gì với "danh tính"? Hai quá tải của 'std :: forward' hoặc' remove_reference :: type'? –
kennytm
danh tính đề cập đến cấu trúc nhận dạng, loại đối số chuyển tiếp: _Ty && forward (typename identity <_Ty> :: type & _Arg) –
Đó phải là một số chữ ký chuẩn. Một tiêu chuẩn là 'T && forward (typename remove_reference :: type & t)' (và quá tải lấy '&&'). –
kennytm