C ++ 20 giới thiệu std::common_reference
. Mục đích của nó là gì? Ai đó có thể cho một ví dụ về việc sử dụng nó?
C ++ 20 giới thiệu std::common_reference
. Mục đích của nó là gì? Ai đó có thể cho một ví dụ về việc sử dụng nó?
Câu trả lời:
common_reference
xuất phát từ những nỗ lực của tôi để đưa ra khái niệm về các trình lặp của STL có khả năng hỗ trợ các trình vòng lặp proxy.
Trong STL, các trình vòng lặp có hai loại lợi ích đặc biệt liên quan: reference
và value_type
. Cái trước là kiểu trả về của iterator operator*
, và value_type
là kiểu (không tham chiếu, không tham chiếu) của các phần tử của chuỗi.
Các thuật toán chung thường có nhu cầu thực hiện những việc như thế này:
value_type tmp = *it;
... vì vậy chúng tôi biết rằng phải có một số mối quan hệ giữa hai loại này. Đối với các trình vòng lặp không proxy, mối quan hệ rất đơn giản: reference
luôn luôn value_type
, tùy chọn const và tham chiếu đủ điều kiện. Những nỗ lực ban đầu trong việc xác định InputIterator
khái niệm đòi hỏi biểu thức có thể *it
chuyển đổi được const value_type &
và đối với hầu hết các trình vòng lặp thú vị là đủ.
Tôi muốn các trình vòng lặp trong C ++ 20 mạnh hơn thế này. Ví dụ, hãy xem xét các nhu cầu của một zip_iterator
lặp đi lặp lại hai chuỗi trong bước khóa. Khi bạn hủy đăng ký a zip_iterator
, bạn sẽ nhận được tạm thời pair
hai loại lặp reference
. Vì vậy, zip
'a vector<int>
và a vector<double>
sẽ có các loại liên quan:
zip
iterator's reference
: pair<int &, double &>
zip
iterator's value_type
:pair<int, double>
Như bạn có thể thấy, hai loại này không liên quan với nhau chỉ đơn giản bằng cách thêm trình độ cv- và ref cấp cao nhất. Và để cho hai loại khác nhau tùy ý cảm thấy sai. Rõ ràng có một số mối quan hệ ở đây. Nhưng mối quan hệ là gì và những thuật toán chung có thể hoạt động trên các trình vòng lặp có thể giả định một cách an toàn về hai loại?
Câu trả lời trong C ++ 20 là đối với bất kỳ loại trình vòng lặp hợp lệ, proxy hay không, các loại reference &&
và value_type &
chia sẻ một tham chiếu chung . Nói cách khác, đối với một số trình vòng lặp, it
có một số loại CR
làm cho các hình thức sau được hình thành rõ ràng:
void foo(CR) // CR is the common reference for iterator I
{}
void algo( I it, iter_value_t<I> val )
{
foo(val); // OK, lvalue to value_type convertible to CR
foo(*it); // OK, reference convertible to CR
}
CR
là tài liệu tham khảo phổ biến. Tất cả các thuật toán có thể dựa vào thực tế là loại này tồn tại và có thể sử dụng std::common_reference
để tính toán nó.
Vì vậy, đó là vai trò common_reference
trong STL trong C ++ 20. Nói chung, trừ khi bạn đang viết các thuật toán chung hoặc các trình vòng lặp proxy, bạn có thể bỏ qua nó một cách an toàn. Nó nằm dưới vỏ bọc đảm bảo rằng các trình lặp của bạn đang đáp ứng các nghĩa vụ theo hợp đồng của họ.
EDIT: OP cũng yêu cầu một ví dụ. Đây là một chút giả tạo, nhưng hãy tưởng tượng nó C ++ 20 và bạn có một phạm vi truy cập ngẫu nhiên r
của các loại R
về mà bạn không biết gì, và bạn muốn sort
phạm vi.
Hơn nữa hãy tưởng tượng rằng vì một số lý do, bạn muốn sử dụng một hàm so sánh đơn hình, như thế nào std::less<T>
. (Có lẽ bạn đã type-xóa dãy núi này, và bạn cần phải cũng gõ-xóa chức năng so sánh và vượt qua nó thông qua một virtual
? Một lần nữa, một căng ra.) Điều gì nên T
được std::less<T>
? Cho rằng bạn sẽ sử dụng common_reference
, hoặc người trợ giúp iter_common_reference_t
được thực hiện về mặt đó.
using CR = std::iter_common_reference_t<std::ranges::iterator_t<R>>;
std::ranges::sort(r, std::less<CR>{});
Điều đó được đảm bảo để hoạt động, ngay cả khi phạm vi r
có các trình vòng lặp proxy.
pair<T&,U&>
và pair<T,U>&
sẽ có một tài liệu tham khảo chung, và nó sẽ đơn giản pair<T&,U&>
. Tuy nhiên, đối std::pair
, không có chuyển đổi từ pair<T,U>&
tới pair<T&,U&>
mặc dù một sự chuyển đổi đó là âm thanh về nguyên tắc. (Điều này, tình cờ, là lý do tại sao chúng ta không có zip
chế độ xem trong C ++ 20.)
pair
, thay vì một loại có thể được thiết kế riêng cho mục đích của nó , với chuyển đổi ngầm thích hợp khi cần thiết?
std::pair
; bất kỳ loại giống cặp nào phù hợp với các chuyển đổi phù hợp sẽ thực hiện và phạm vi-v3 xác định loại giống như cặp đó. Trong Ủy ban, LEWG không thích ý tưởng thêm vào Thư viện tiêu chuẩn một loại gần như nhưng không hoàn toàn std::pair
, có thể là quy tắc hay không, mà không cần thực hiện chuyên sâu về những ưu và nhược điểm của việc đơn giản là làm std::pair
việc.
tuple
, pair
, tomato
, to
- MAH
- to
. pair
có tính năng hay này mà bạn có thể truy cập các yếu tố với .first
và .second
. Các ràng buộc có cấu trúc giúp với một số khó xử khi làm việc với tuple
s, nhưng không phải tất cả.