在const成员函数中,std::upper_bound返回const迭代器。

9
这是一个包含某些结构体的boost::circular_buffer的类。我对包含的进行了迭代器别名定义(typedef)。

我的问题在于当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会导致这种副作用吗?我想要一个非const迭代器进入容器,但在我的实际测试中,我并不打算修改容器。


4
既然doWorkconst的,因此cb也被视为const。由于doWork没有意图修改cb,请改用const_iterator - Captain Obvlious
2
一个MCVE!奇迹从未停止。+1 - Lightness Races in Orbit
1
@CaptainObvlious:答案部分在下面,朋友。 - Lightness Races in Orbit
2
为什么不直接使用 auto iter = std::upper_bound(... 呢? - Galik
@Galik 对于 auto,我也赞同,特别是因为这被标记为 c++11。 - TemplateRex
2个回答

8

由于您实际上是观察一个const容器,因此您需要使用const_iterator

也许:

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

... 然后将 iter 设置为其中之一。

有人可能会告诉你,你可以通过使用 auto 避免这种情况。这是正确的,但是你就不能发现这个“错误”,或者了解到 const_iterator 的存在。


4
如果您的函数标记为const,那么您对成员变量的所有访问也将是constconst容器只允许访问const_迭代器,这就是迭代器的工作方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接