Theo như tôi hiểu C++ 11 tài liệu tham khảo, tôi không nên ràng buộc một tham chiếu rvalue đến một tham chiếu lvalue (non-const) như trước đây có thể được ràng buộc với một tạm thời và sau này không bao giờ bị ràng buộc với một tạm thời.Tại sao tôi có thể std :: di chuyển ref rvalue stream vào ref ref lvalue?
Tuy nhiên tôi thấy hành vi này lẻ kết hợp đối tượng dòng tạm thời (mà tôi giảm như xa như tôi có thể)
struct Dummy {};
template <typename Stream>
Stream& operator<<(Stream& s, Dummy) {
return s << "."; // <- (A)
}
template <typename Stream>
void pass(Stream&& s) {
std::move(s) << Dummy(); // <- (X) rvalue->lvalue conversion?
}
#include <fstream>
int main() {
pass(std::fstream("test",std::ios::out));
}
Nếu tôi viết s << Dummy()
trong dòng (X)
, C++ phàn nàn phù (A)
, nói
error: invalid initialization of reference of type ‘std::basic_fstream<char>&’ from expression of type ‘std::basic_ostream<char>’
Tuy nhiên, tại sao mã (như được hiển thị ở trên) biên dịch và hoạt động như mong đợi? Tham chiếu rvalue được trả về bởi std::move
chỉ nên không thể bị ràng buộc với tham chiếu giá trị bằng lóng như biểu thức s
, nhưng cả hai số gcc 4.6.1
và gcc 4.7.2
đều phản ứng giống nhau.
Và tại sao hiện tượng này chỉ xuất hiện để hoạt động với luồng? Khi trực tiếp chuyển một Dummy&&
đến một hàm mong đợi một T&
không thành công cả khi có và không có std::move
.
Tôi hiểu. Điều đó có ý nghĩa. Nhưng tại sao 'std :: move' lại cần thiết, vậy thì sao? – bitmask
@bitmask: Bởi vì không có nó 's' không thể liên kết với một tham chiếu rvalue, cho rằng nó là một lvalue. –
@KerrekSB: Nhưng nó có một quá tải hoàn toàn tốt cho một dòng tham chiếu rvalue để ràng buộc với (như được hiển thị trong câu trả lời này). Tại sao không phải là quá tải phù hợp mà không khuyến khích từ 'std :: move'? – bitmask