std::upper_bound возвращает константный итератор в константной функции-члене

Вот класс, который содержит boost::circular_buffer некоторых struct, Я делаю typedef для итераторов в содержащийся circular_buffer,

Моя проблема заключается в следующем: когда doWork функция помечена constВозвращаемое значение 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;
}

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

2 ответа

Решение

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

Может быть:

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

... тогда сделай iter один из них.

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

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

const Контейнер позволит только доступ к const_ итераторы, это просто способ работы итераторов.

Другие вопросы по тегам