2009-10-20 26 views
11

Tôi có một lớp mà tôi muốn hiển thị danh sách các cấu trúc (chỉ chứa một số số nguyên). Tôi không muốn bên ngoài để sửa đổi các dữ liệu, chỉ cần lặp trên nó và đọc chúng Ví dụ:Làm cho lớp C++ của tôi có thể lặp lại được qua BOOST_FOREACH

struct TestData 
{ 
    int x; 
    int y; 
    // other data as well 
} 

class IterableTest 
{ 
    public: 
    // expose TestData here 
}; 

bây giờ trong mã của tôi Tôi muốn sử dụng lớp học của tôi như thế này:

IterableTest test; 
BOOST_FOREACH(const TestData& data, test.data()) 
{ 
    // do something with data 
} 

Tôi đã đọc bài viết này http://accu.org/index.php/journals/1527 về không gian thành viên. Tuy nhiên, tôi không muốn (hoặc không thể) lưu tất cả TestData trong một vector nội bộ hoặc một cái gì đó. Điều này là do chính lớp đó không sở hữu bộ nhớ, nghĩa là không có vùng chứa cơ bản nào có thể được lớp truy cập trực tiếp. Bản thân lớp có thể truy vấn một thành phần bên ngoài để lấy phần tử tiếp theo, trước đó hoặc thứ i.

Vì vậy, về cơ bản tôi muốn lớp học của tôi cư xử như thể nó có một bộ sưu tập, nhưng trên thực tế nó không có. Bất kỳ ý tưởng nào?

+4

bạn không phải cung cấp chức năng bắt đầu/kết thúc trả về trình lặp thích hợp? – jalf

+0

có, nhưng tôi không có một thùng chứa cơ bản mà có thể cung cấp cho tôi với các iterators – newgre

+0

để viết chúng cho mình. :) Thư viện Boost.Iterator sẽ giúp bạn khởi động và chạy khá nhanh. – jalf

Trả lời

5

Có vẻ như bạn phải viết lặp của riêng bạn.

Thư viện Boost.Iterator có một số mẫu hữu ích. Tôi đã sử dụng lớp cơ sở Iterator Facade của họ một vài lần, và thật dễ dàng và dễ dàng để định nghĩa các trình vòng lặp của riêng bạn bằng cách sử dụng nó.

Nhưng ngay cả khi không có nó, vòng lặp không phải là khoa học tên lửa. Họ chỉ cần để lộ các nhà khai thác và typedef. Trong trường hợp của bạn, chúng sẽ chỉ là hàm bao quanh hàm truy vấn mà chúng phải gọi khi chúng được tăng lên.

Khi bạn đã xác định một lớp trình lặp, bạn chỉ cần thêm begin()end() chức năng thành viên vào lớp học của mình.

Có vẻ như ý tưởng cơ bản là phải gọi hàm truy vấn của bạn khi trình vòng lặp được tăng lên, để nhận giá trị tiếp theo. Và dereference sau đó sẽ trả về giá trị được truy xuất từ ​​cuộc gọi truy vấn cuối cùng.

Nó có thể giúp bạn xem xét thư viện chuẩn stream_iterator s vì một số ngữ nghĩa, vì chúng cũng phải làm việc xung quanh một số loại cá "chúng tôi không thực sự có thùng chứa và chúng tôi không thể tạo vòng lặp ở bất kỳ nơi nào khác ngoài vấn đề vị trí luồng hiện tại ". Ví dụ: giả sử bạn cần gọi hàm query() trả về NULL khi bạn đã đến cuối chuỗi, việc tạo "trình kết thúc" sẽ khó khăn Nhưng thực sự, tất cả những gì bạn cần là xác định sự bình đẳng để "các trình vòng lặp là bình đẳng nếu cả hai lưu trữ NULL như giá trị được lưu trữ của chúng". Vì vậy, khởi tạo iterator "kết thúc" với NULL.

Nó có thể giúp tìm kiếm các ngữ nghĩa bắt buộc cho các trình vòng lặp đầu vào hoặc nếu bạn đang đọc tài liệu cho Boost.Iterator, cho các trình vòng lặp một lần. Có thể bạn sẽ không thể tạo các trình lặp vòng đa. Vì vậy, hãy tra cứu chính xác hành vi nào là bắt buộc đối với một trình lặp vòng một lần và gắn bó với điều đó.

+0

Và bởi vì tôi là một người tốt: Khái niệm Iterator đầu vào >> http://www.sgi.com/tech/stl/InputIterator.html –

0

Nếu loại bộ sưu tập của bạn trình bày giao diện vùng chứa chuẩn, bạn không cần phải làm bất kỳ điều gì để làm cho BOOST_FOREACH hoạt động với loại của bạn. Nói cách khác, nếu loại của bạn có iteratorconst_iterator typedefs lồng nhau và begin()end() chức năng thành viên, BOOST_FOREACH đã biết cách lặp qua loại của bạn. Không có thêm hành động được yêu cầu.

http://boost-sandbox.sourceforge.net/libs/foreach/doc/html/boost_foreach/extending_boost_foreach.html

+0

Tôi biết về điều đó, nhưng tôi sẽ lấy các trình vòng lặp đó từ đâu? Không có container bên dưới có trình vòng lặp mà tôi có thể sử dụng – newgre

0

Từ trang tài liệu for_each Boost:

lặp BOOST_FOREACH trên chuỗi. Nhưng những gì đủ điều kiện như một chuỗi, chính xác? Kể từ khi BOOST_FOREACH được xây dựng trên đầu trang của Boost.Range, nó sẽ tự động hỗ trợ những loại mà Boost.Range công nhận là chuỗi. Cụ thể, BOOST_FOREACH hoạt động với các kiểu thỏa mãn Khái niệm Phạm vi Đơn. Ví dụ: chúng tôi có thể sử dụng BOOST_FOREACH với:

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