Tôi thấy bản thân mình phải xác định các loại thực hiện tính năng này nhiều lần. Tôi không biết nếu phát minh ra một khái niệm "đặc biệt" là thanh lịch (tưởng tượng rằng nó là một khái niệm liên quan đến bộ nhớ, không phải là rất trừu tượng) nhưng tôi đồng ý một cái gì đó như thế này sẽ hữu ích.
Trong khi thực tế và dịch khái niệm/yêu cầu này thành yêu cầu cú pháp thuần túy, hãy quay lại. Nếu chúng ta hạn chế bản thân với tiêu chuẩn, các lớp học đảm bảo (hoặc gần như đảm bảo) là gì? theo thứ tự liên quan:
std::vector<T>
T[N] // !!
std::array<T, N>
std::string
std::initializer_list<T>
std::valarray<T>
Trong tất cả các, std::vector
, std::array
, std::string
có một hàm thành viên được gọi là .data()
. Vì vậy, nếu điều này là đủ cho bạn, có thể dựa vào sự hiện diện của thành viên .data() -> T*
để chỉ bộ nhớ tiếp giáp.
Bạn có hai lựa chọn:
1) Tận dụng tối nỗ lực để sử dụng chức năng thành viên .data()
để nâng cao một lỗi cú pháp nếu loại là không tiếp giáp. (Không khó nếu bạn thay thế ví dụ t[0]
bởi *t.data()
)
2) Sử dụng một số loại SFINAE trên .data()
.
template<class ContiguousSequence, typename = decltype(std::declval<ContigiousSequence>().data())>
void fun(ContiguousSequence&& s){...} // this function will only work with contiguous data
Hơn nữa, C++ 17 có std::data
mà khái quát nó cho tất cả các loại với .data()
và quá tải bổ sung cho T[N]
và std::initializer_list<T>
. Vì vậy, bạn có thể thay thế ....data()
theo số std::data(...)
ở trên.
Kết luận, tôi nghĩ rằng đó là một quy ước tốt lành là nếu một loại có chức năng data
(hoặc .data()
trong C++ 11) trả về một con trỏ đến kiểu giá trị sau đó các yếu tố là tiếp giáp.
(Ok, những gì về std::valarray<T>
? Nó không làm việc, trừ khi bạn quá tải std::data(std::valarray<T>&)
. Nhưng ai sử dụng std::valarray
không? Nó là một góc khá bị bỏ rơi của C++, tôi nghĩ)
Cuối cùng, lưu ý cho ví dụ rõ ràng là std::map
và ít rõ ràng là std::deque
không có chức năng .data()
(hoặc std::data(...)
). boost::multi_array<..., N>
có một thành viên .data()
và trả về một con trỏ đến phần tử mảng, không rõ ràng nếu đây là chuỗi liên tiếp theo ý bạn muốn (vì thứ tự không rõ ràng) nhưng theo một nghĩa nào đó nó cũng là một bộ nhớ liên tiếp.
EDIT: Có hai đề xuất hiện giải quyết vấn đề này (nhưng ở cấp độ của các vòng lặp) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3884.pdfhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4284.html
'std :: array';) – Zeta
Theo như tôi biết, không có khái niệm như vậy. 'std :: vector',' std :: string' và 'std :: array' chỉ đơn giản là có bất biến là' c.data() + i == & c [i] 'cho' i' trong '[0, c .size()) '. – Xeo
@Xeo: Đúng vậy. Không có khái niệm, chỉ yêu cầu các phần tử (hoặc 'char_type's) là *" được lưu trữ liên tục "*. – Zeta