2013-09-27 106 views
10

Trong tiêu chuẩn C++ 11 nó nói rằng (xem cppreference.com, xem thêm phần 20.4.2.4 của tiêu chuẩn) nó nói rằngTại sao std :: make_tuple turn std :: reference_wrapper <X> đối số vào X &?

template< class... Types > 
tuple<VTypes...> make_tuple(Types&&... args); 

Tạo một đối tượng tuple, suy diễn ra kiểu mục tiêu từ các loại của các đối số.

Đối với mỗi Ti trong Types..., tương ứng loại Vi trong Vtypes...std::decay<Ti>::type trừ khi áp dụng std::decay kết quả trong std::reference_wrapper<X> đối với một số loại X, trong trường hợp này loại suy luận là X&.

Tôi tự hỏi: Tại sao trình bao bọc tham chiếu được xử lý đặc biệt ở đây?

+0

Tôi nghĩ điểm chính là 'std :: reference_wrapper' là điểm đánh dấu thông thường (được xử lý đặc biệt) cần thiết trước khi tham chiếu rvalue, xem http://stackoverflow.com/questions/20080493/semantics-for-wrapped-objects -reference-value-by-default-via-stdmove-stdref? rq = 1. Tôi nghĩ rằng nó cần thiết nữa trong C++ 11 nhưng quy ước vẫn tồn tại. – alfC

Trả lời

11

Điều này ít nhiều là mục đích chính của reference_wrapper.

Thông thường, std::make_tuple luôn tạo các giá trị giá trị (std::decay mô phỏng ngữ nghĩa theo giá trị). Cho int x, y; std::make_tuple(x, y); tạo một std::tuple<int, int>, mặc dù nó sẽ khấu trừ Types dưới dạng gói tham chiếu int&, int&. std::decay chuyển đổi những người đó thành int, int.

reference_wrapper cho phép bạn bắt buộc tạo các bộ tham chiếu tham chiếu: std::make_tuple(std::ref(x), y) sẽ tạo std::tuple<int&, int>.

Các phần khác của việc sử dụng thư viện chuẩn reference_wrapper theo cách tương tự. Ví dụ, std::bind thường sẽ sao chép/di chuyển các đối số bị ràng buộc vào đối tượng kết quả, nhưng nếu bạn muốn nó chỉ lưu trữ một tham chiếu, bạn có thể yêu cầu nó một cách rõ ràng bằng cách chuyển một số reference_wrapper.

+0

Lưu ý rằng điều này làm cho nó không thể 'make_tuple' và tạo một' tuple' chứa 'std :: reference_wrapper ', nhưng bạn có thể 'make_tuple' và tạo một' tuple' chứa 'std :: reference_wrapper &'. Tôi thấy điều này thật thú vị. – Yakk

+0

Vâng, nhưng có rất ít lợi thế của một bộ tham chiếu_wrappers trên một bộ tham chiếu. –

4

Tiêu đề của bạn gây hiểu lầm: sử dụng std::reference_wrapper<X> biến các thành viên thành X& thay vì X. Lý do biến đổi này được thực hiện là std::reference_wrapper<T> là một loại phụ trợ, có nghĩa là để biến một loại giá trị thành một loại tham chiếu. Tuy nhiên, chuyển đổi thêm cần thiết để làm cho nó xuất hiện theo cách đó đôi khi can thiệp vào việc sử dụng. Do đó, hãy mở tài liệu tham khảo nếu có thể có vẻ là một cách tiếp cận hợp lý: làm cho thành viên std::tuple<...>T& làm cho việc sử dụng tự nhiên hơn.

0

Mọi người thường sử dụng std::reference_wrapper<X> để giữ các loại không thể sao chép. Vì vậy, sao chép chúng trong make_tuple sẽ đánh bại mục đích (và có thể phá vỡ xây dựng nếu các nhà xây dựng bản sao bị xóa). Đó là lý do tại sao nó sử dụng tham chiếu (thay vì một giá trị) trong kiểu trả về của nó.

Các vấn đề liên quan