2012-01-12 21 views
8

Tôi có chứa này:Tôi làm cách nào để sử dụng BOOST_FOREACH với vùng chứa chỉ hỗ trợ const_iterator?

class /*final*/ Row 
{ 
public: 
    typedef FieldIterator const_iterator; 
    typedef FieldIterator iterator; 
    FieldIterator begin() const; 
    FieldIterator end() const; 
    FieldIterator begin(); 
    FieldIterator end(); 
    ... 
}; 

Cho rằng, đoạn mã sau biên dịch tốt:

BOOST_FOREACH(Field field, row) 
{ 
} 

Tuy nhiên, lớp không có iterator mutable, do đó, tôi đã thay đổi lớp Row, bằng cách xóa quyền truy cập có thể thay đổi:

class /*final*/ Row 
{ 
public: 
    typedef FieldIterator const_iterator; 
    FieldIterator begin() const; 
    FieldIterator end() const; 
    ... 
}; 

Nhưng bây giờ cùng vòng lặp foreach không biên dịch:

1>o:\c\boost_1_48_0\boost\foreach.hpp(364): error C2039: 'type' : is not a member of 'boost::mpl::eval_if<C,F1,F2>' 
1>   with 
1>   [ 
1>    C=boost::mpl::false_, 
1>    F1=boost::range_const_iterator<sqlserver::Row>, 
1>    F2=boost::range_mutable_iterator<sqlserver::Row> 
1>   ] 
1>   c:\dev\internal\playmssqlce\playmssqlce.cpp(29) : see reference to class template instantiation 'boost::foreach_detail_::foreach_iterator<T,C>' being compiled 
1>   with 
1>   [ 
1>    T=sqlserver::Row, 
1>    C=boost::mpl::false_ 
1>   ] 
... 

Từ thông báo lỗi Tôi hiểu rằng BOOST_FOREACH cố gắng khởi tạo loại range_mutable_iterator, điều này rõ ràng là không thành công. Làm thế nào để làm cho nó để nhanh chóng phạm vi liên tục thay thế?

Cảm ơn.

EDIT

Đây là tờ khai lớp hoàn chỉnh cho và :

class /*final*/ Row 
{ 
    const BYTE *m_buffer; 
    const DBBINDING *m_pColumnBindings; 
    int m_columnBindingCount; 
    FieldIterator m_end; 
public: 
    typedef FieldIterator const_iterator; 
    typedef FieldIterator iterator; 
    Row(const BYTE *buffer, const DBBINDING *pColumnBindings, int columnBindingCount); 
    bool isSameRow(const Row& r) const; 
    int fieldCount() const; 
    Field field(int i) const; 
    Field& field(int i, void *fieldBuffer) const; 
    FieldIterator begin() const; 
    FieldIterator end() const; 
    FieldIterator begin(); 
    FieldIterator end(); 
}; 

class FieldIterator : public iterator_facade<FieldIterator, Field, boost::random_access_traversal_tag> 
{ 
    const Row *m_pRow; 
    int m_index; 
    mutable BYTE m_fieldBuffer[sizeof(Field)]; 
public: 
    FieldIterator(const Row *pRow = NULL, int index = 0); 
private: 
    friend class boost::iterator_core_access; 
    void increment(); 
    void decrement(); 
    void advance(difference_type n); 
    difference_type distance_to(FieldIterator it); 
    reference dereference() const; 
    bool equal(const FieldIterator& rhs) const; 
}; 
+1

Có 'BOOST_FOREACH (const Field & field, row)' hoạt động không? – Ferruccio

+0

Cùng một kết quả chính xác. – mark

Trả lời

6

A làm việc xung quanh nếu bạn thực sự muốn tránh thành viên iterator là sử dụng một cặp vòng lặp.

BOOST_FOREACH(Field field, std::make_pair(row.begin(), row.end())) 
+0

OK, nó hoạt động. Vấn đề duy nhất là nó hơi quá chi tiết, nhưng không có gì không thể sửa được bằng macro. – mark

0

dường như là lớp iterator tương tự cho const và phương pháp lặp không const. BOOST_FOREACH hoạt động với bất kỳ vùng chứa nào bao gồm các mảng kiểu C khiến tôi nghĩ rằng vấn đề nằm trong lớp . Bạn có thể đăng mã cho nó không?

+0

Xong - xem thay đổi trong phần nội dung của câu hỏi. – mark

5

Điều gì đã xảy ra với mã ban đầu của bạn?

Một số vùng chứa thư viện chuẩn, như std::setstd::multiset, có trình lặp tất cả là const (không được phép cập nhật). Tiêu chuẩn cụ thể cho biết:

Đối với các vùng chứa liên kết nơi loại loại giá trị giống như loại khóa, cả trình lặp và bộ kiểm định là các trình lặp không đổi. Nó là không xác định có hay không trình lặp và const_iterator cùng loại.

Bạn có lẽ sẽ nhận được ngay với

typedef const_iterator iterator; 

trong lớp học của bạn.

+0

Vùng chứa của tôi không phải là vùng chứa liên kết. Do đó đoạn văn không áp dụng cho mã của tôi. – mark

+0

Nếu bạn xác định vùng chứa của riêng mình, bạn có thể xác định nó theo bất kỳ cách nào bạn muốn. Tôi chỉ muốn chỉ ra rằng một số thùng chứa tiêu chuẩn có các trình vòng lặp mà chỉ có quyền truy cập chỉ đọc vào các phần tử. Đoán * họ * làm việc với Boost! –

+0

Tôi không muốn xác định các phiên bản có thể thay đổi của phương thức 'begin()' và 'end()'. Lời khuyên của bạn là hợp pháp, nhưng loại bỏ hoàn toàn API có thể thay đổi, nếu có thể, tốt hơn là rút ngắn nó thành API const. – mark

0

Với tăng 1.52 (Tôi chưa thử nghiệm với các phiên bản khác), BOOST_FOREACH(Field field, const_cast<Row const&>(row)) cũng sẽ hoạt động.

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