2016-08-30 14 views
9

Đây là lớp có chứa boost::circular_buffer của một số struct. Tôi tạo một typedef cho các trình vòng lặp vào trong số circular_buffer.std :: return_bound trả về const iterator trong hàm thành viên const

Vấn đề của tôi là thế này: khi chức năng doWork được đánh dấu const, giá trị trả về của std::upper_bound không tương thích với các loại MyIterator do giá trị trả về có boost::cb_details::const_traits. Nếu tôi xóa từ khóa const khỏi hàm, tất cả các lỗi biên dịch của tôi sẽ biến mất.

Để được rõ ràng lỗi biên dịch là thế này:

error: conversion from ‘boost::cb_details::iterator<boost::circular_buffer<Wrapper<int>::Sample, std::allocator<Wrapper<int>::Sample> >, boost::cb_details::const_traits<std::allocator<Wrapper<int>::Sample> > >’ to non-scalar type ‘Wrapper<int>::MyIterator {aka boost::cb_details::iterator<boost::circular_buffer<Wrapper<int>::Sample, std::allocator<Wrapper<int>::Sample> >, boost::cb_details::nonconst_traits<std::allocator<Wrapper<int>::Sample> > >}’ requested  
          [](const Sample& a, const Sample& b) { return a.foo < b.foo; }); 

Đây là một khép kín dụ:

#include <algorithm> 
#include <boost/circular_buffer.hpp> 

template <typename T> 
class Wrapper { 
public: 
    struct Sample { 
     T foo; 
    }; 

    typedef typename boost::circular_buffer<Sample>::iterator MyIterator; 

    Wrapper(int size) { cb.resize(size); } 

    void add(T val) { cb.push_back(Sample{val}); } 

    void doWork(T bound) const { 
     MyIterator iter = 
      std::upper_bound(cb.begin(), cb.end(), Sample{3}, 
         [](const Sample& a, const Sample& b) { return a.foo < b.foo; }); 
    } 

    boost::circular_buffer<Sample> cb; 
}; 

int main() { 
    Wrapper<int> buf(100); 
    buf.add(1); 
    buf.add(5); 
    buf.doWork(3); 
    return 0; 
} 

Vì vậy, tại sao có thể không hoạt động này được const? Tại sao đánh dấu nó const có tác dụng phụ này? Tôi muốn một iterator không const vào container, nhưng trong trường hợp thử nghiệm thực sự của tôi, tôi không có ý định thực sự sửa đổi container.

+4

Cũng vì 'doWork' là' const', 'cb' cũng được coi là' const'. Vì 'doWork' không có ý định sửa đổi' cb' sử dụng 'const_iterator' thay thế. –

+2

Một MCVE! Kỳ quan không bao giờ chấm dứt. +1 –

+1

@CaptainObvlious: Phần trả lời nằm bên dưới, bạn bè –

Trả lời

7

Bạn sẽ cần một const_iterator, vì bạn đang quan sát hiệu quả vùng chứa const.

lẽ:

typedef typename boost::circular_buffer<Sample>::const_iterator MyConstIterator; 

& hellip; sau đó thực hiện iter một trong số này.

Ai đó sẽ cho bạn biết rằng bạn có thể tránh điều này bằng auto. Đó là sự thật, nhưng sau đó bạn sẽ không bao giờ phát hiện ra "lỗi" này, hoặc rằng tồn tại const_iterator.

+0

Thực tế bây giờ tôi hiểu const_iterators, cảm ơn! – Chris

4

Nếu chức năng của bạn được đánh dấu const thì tất cả quyền truy cập của bạn vào các biến thành viên cũng sẽ là const.

Vùng chứa const sẽ chỉ cho phép truy cập vào các trình vòng lặp const_, đó chỉ là cách trình vòng lặp hoạt động.

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