Thực ra, đây là một câu hỏi rất hay. Cho đến nay tôi cũng đã sử dụng thủ thuật tham chiếu chung cộng với búa enable_if
. Ở đây tôi trình bày một giải pháp không sử dụng các khuôn mẫu và sử dụng cách viết lvalue như một sự thay thế.
Dưới đây là ví dụ thực tế khi tình huống phát sinh bằng cách sử dụng ví dụ được sử dụng tại chỗ ofstream
không thể (hoặc rất khó) trong C++ 98 (tôi sử dụng ostringstream
trong ví dụ để làm rõ hơn).
Trước tiên, bạn sẽ thấy một hàm về tham chiếu lvalue như thường thấy trong C++ 98.
#include<iostream>
#include<sstream>
struct A{int impl_;};
std::ostringstream& operator<<(std::ostringstream& oss, A const& a){
oss << "A(" << a.impl_ << ")"; // possibly much longer code.
return oss;
}
// naive C++11 rvalue overload without using templates
std::ostringstream& operator<<(std::ostringstream&& oss, A const& a){
oss << "A(" << a.impl_ << ")"; // ok, but there is code repetition.
return oss;
}
int main() {
A a{2};
{// C++98 way
std::ostringstream oss;
oss << a;
std::cout << oss.str() << std::endl; // prints "A(2)", ok"
}
{// possible with C++11, because of the rvalue overload
std::cout << (std::ostringstream() << a).str() << std::endl; //prints "A(2)", ok
}
}
Như bạn có thể thấy trong C++ 11, chúng tôi có thể đạt được những gì chúng tôi không thể có trong C++ 98. Đó là sử dụng ostringstream
(hoặc ofstream
) tại chỗ. Bây giờ đến câu hỏi OP, hai quá tải trông rất giống nhau, cả hai có thể được tham gia vào một?
Một tùy chọn là sử dụng tham chiếu chung (Ostream&&
) và tùy chọn với enable_if
để hạn chế loại. Không phải rất thanh lịch.
Những gì tôi tìm thấy bằng cách sử dụng ví dụ "thế giới thực" này là nếu muốn sử dụng cùng một mã cho ref lvalue và ref rvalue là vì có lẽ bạn có thể chuyển đổi một cái khác!
std::ostringstream& operator<<(std::ostringstream&& oss, A const& a){
return operator<<(oss, a);
}
này trông giống như một chức năng vô hạn đệ quy, nhưng nó không phải là vì oss
là một tài liệu tham khảo giá trị trái (có, nó là một tài liệu tham khảo giá trị trái bởi vì nó có một cái tên). Vì vậy, nó sẽ gọi quá tải khác.
Bạn vẫn phải viết hai hàm nhưng một hàm có mã mà bạn không phải duy trì. Tóm lại, nếu "có ý nghĩa" © để áp dụng một hàm cho cả tham chiếu và giá trị rvalue (không const) cũng có nghĩa là bạn có thể chuyển đổi giá trị rvalue thành một giá trị và do đó bạn chuyển tiếp đến một hàm duy nhất. Lưu ý rằng "nó có ý nghĩa" phụ thuộc vào ngữ cảnh và ý nghĩa của mã dự kiến, và nó là một cái gì đó mà chúng ta phải "nói" trình biên dịch bằng cách explictly gọi quá tải lvalue.
Tôi không nói rằng điều này là tốt hơn so với sử dụng tham chiếu phổ quát, tôi nói đó là một thay thế và cho là ý định rõ ràng hơn.
Mã có thể chỉnh sửa tại đây: http://ideone.com/XSxsvY. (Phản hồi được hoan nghênh)
Không có điểm nào chuyển một kiểu đơn giản như 'int' theo rvalue. Trong trường hợp tổng quát hơn, tôi tin C++ 11 có một trường hợp đặc biệt cho điều này, trong đó tham số rvalue sẽ được đọc dưới dạng tham số rvalue * hoặc * lvalue. Tôi không thể nhớ chính xác tình huống mà áp dụng mặc dù. – Dave
Vì vậy, bạn muốn 'x' là tham chiếu rvalue (nếu tham chiếu rvalue được truyền) hay tham chiếu lvalue tới' const'? Tôi hiểu chính xác, rằng 'X &&' sẽ không được chấp nhận cho bạn bởi vì nó sẽ là một tham chiếu lvalue để không 'const' khi một lvalue được thông qua? –
Ở đây chúng tôi đi, tôi tin rằng bạn đang cố gắng làm điều này: http://thbecker.net/articles/rvalue_references/section_07.html được giải thích bằng cách sử dụng giá trị trong trang tiếp theo. Yell nếu tôi hiểu lầm câu hỏi. – Dave