1. Vấn đề nó giải quyết
Pipeline có thể cần phần tử chỉ đọc hoặc quyền move phần tử khỏi nguồn. C++23 cung cấp views::as_const và views::as_rvalue, còn adaptor closure cho thư viện thêm phép biến đổi dùng được với pipe.
2. Kiến thức cần có
Ngày 29: chiếu category cv/ref.
Ngày 39 và 44–45: const range và pipeline adaptor.
3. Ý tưởng cốt lõi
Các view này đổi thấu kính truy cập, không đổi storage. Custom adaptor là thấu kính tái sử dụng có cách viết range | adaptor và forward range nền rõ ràng. Hãy xác định giá trị đang được biến đổi rồi kiểm tra kiểu, lifetime hoặc quyền sở hữu kết quả. Bật C++23 chưa chắc thư viện đã triển khai đủ, vì vậy cần kiểm tra feature-test macro liên quan.
4. Cú pháp tối thiểu
auto read_only = range | std::views::as_const;5. Cách nó hoạt động
Ví dụ tạo biểu thức hoặc đối tượng nhỏ nhất cho
as_const,as_rvaluevà custom range adaptor.Chương trình cung cấp có điều kiện truy cập const, rvalue và pipe range qua custom take adaptor nhỏ.
Cuối cùng, nó in hoặc kiểm tra tham chiếu chỉ đọc, tham chiếu movable và custom view có giới hạn để dễ đối chiếu.
6. Lỗi thường gặp
Đọc từ view
as_rvaluetự nó chưa move, nhưng tiêu thụ phần tử vào object mới có thể để source ở trạng thái moved-from; custom adaptor giữ tham chiếu đến temporary có thể treo.Không kiểm tra feature-test macro có thể chọn nhánh mã thư viện hiện tại chưa hỗ trợ.
7. Khi nào nên dùng
Nên dùng khi pipeline generic cố ý kiểm soát khả năng sửa hoặc chuyển quyền sở hữu.
Tránh dùng khi dùng
as_rvaluechỉ để mong nhanh hơn mà chưa quyết định source có được tiêu thụ không.
8. Ví dụ đơn giản
Pipeline chuyển move chuỗi từ vector tạm sang storage cuối và không đọc lại giá trị tạm sau đó. Chương trình dùng dữ liệu cố định để output dễ kiểm tra.
Mã mẫu hoàn chỉnh
Tệp mã nguồn
cpp23/46_as_const_as_rvalue_custom_adaptors/main.cpp
#include <iostream>
#include <ranges>
#include <type_traits>
#include <utility>
#include <vector>
#include <version>
#if defined(__cpp_lib_ranges_as_const) && defined(__cpp_lib_ranges_as_rvalue)
struct FirstTwo : std::ranges::range_adaptor_closure<FirstTwo> {
template <std::ranges::viewable_range R>
constexpr auto operator()(R&& range) const {
return std::forward<R>(range) | std::views::take(2);
}
};
#endif
int main() {
#if defined(__cpp_lib_ranges_as_const) && defined(__cpp_lib_ranges_as_rvalue)
std::vector values{1, 2, 3};
auto read_only = values | std::views::as_const;
static_assert(std::is_same_v<
std::ranges::range_reference_t<decltype(read_only)>, const int&>);
auto movable = values | std::views::as_rvalue;
static_assert(std::is_rvalue_reference_v<
std::ranges::range_reference_t<decltype(movable)>>);
for (int value : values | FirstTwo{})
std::cout << value << ' ';
std::cout << '\n';
#else
std::cout << "as_const or as_rvalue views unavailable\n";
#endif
}
9. Điều cần nhớ
Tách quy tắc chuẩn khỏi mức hỗ trợ thực tế.
Làm rõ lifetime, ownership và kiểu suy luận.
Ưu tiên cú pháp ngắn, đúng ý định.
Guard tính năng chưa được hỗ trợ đồng đều.
10. Câu hỏi tự kiểm tra
Dễ — Cú pháp ngắn nhất ở Phần 4 là gì và nhiệm vụ chính của nó là gì?
Trung bình — Đọc chương trình mẫu: giá trị, kiểu hoặc nhánh nào được quan sát, và vì sao?
Khó — Vì sao duyệt
as_rvaluekhông tự sửa source, nhưng tạostd::stringmới từ mỗi phần tử dereference lại có thể sửa trạng thái source?