2016-08-30 4 views
9

Вот класс, который содержит boost::circular_buffer от struct. Я делаю typedef для итераторов в содержащем circular_buffer.std :: upper_bound возвращает const iterator в функции const member

Моя проблема заключается в следующем: когда функция doWorkconst отмечена, то возвращаемое значение std::upper_bound не совместим с MyIterator типа за счет возврата значение, имеющее boost::cb_details::const_traits. Если я удалю ключевое слово const из функции, все мои ошибки компиляции исчезнут.

Чтобы быть ясно, что ошибка компилятора заключается в следующем:

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; }); 

Вот самодостаточным пример:

#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; 
} 

Итак, почему не может эта функция быть константной? Почему эта маркировка имеет этот побочный эффект? Я хочу, чтобы в контейнер был неконтентный итератор, но в моем реальном случае проверки я вообще не намерен изменять контейнер.

+4

Ну, так как 'doWork' является' const', 'cb' также рассматривается как' const'. Поскольку 'doWork' не предназначен для изменения' cb', используйте 'const_iterator' вместо этого. –

+2

MCVE! Чудеса никогда не прекращаются. +1 –

+1

@CaptainObvlious: раздел ответа внизу, друг –

ответ

7

Вам понадобится const_iterator, так как вы эффективно наблюдаете за контейнером const.

Возможно:

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

& hellip; затем сделайте iter одним из них.

Кто-то собирается сказать вам, что вы могли бы избежать этого с помощью auto. Это правда, но тогда вы никогда бы не обнаружили эту «ошибку» или что существует const_iterator.

+0

Теперь я понимаю const_iterators, спасибо! – Chris

4

Если ваша функция отмечена const, тогда ваш доступ к переменным-членам будет также const.

A const контейнер разрешает доступ только к итераторам const_, это именно то, как работают итераторы.