【问题标题】:std::upper_bound returns const iterator in const member functionstd::upper_bound 在 const 成员函数中返回 const 迭代器
【发布时间】:2017-01-07 08:58:44
【问题描述】:

这是一个包含一些structboost::circular_buffer 的类。我为包含的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 会产生这种副作用?我想要一个非常量迭代器进入容器,但在我的真实测试用例中,我根本不打算实际修改容器。

【问题讨论】:

  • 既然doWorkconstcb 也被视为const。由于doWork 不打算修改cb,请改用const_iterator
  • 一个 MCVE!奇迹永远不会停止。 +1
  • @CaptainObvlious:回答部分在下面,朋友
  • 为什么不直接使用auto iter = std::upper_bound(...
  • @Galik amen to auto,尤其是因为它被标记为 c++11

标签: c++ c++11 boost circular-buffer


【解决方案1】:

如果您的函数标记为const,那么您对成员变量的所有访问权限也将是const

const 容器将只允许访问 const_ 迭代器,这正是迭代器的工作方式。

【讨论】:

    【解决方案2】:

    您将需要一个const_iterator,因为您实际上是在观察const 容器。

    也许:

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

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

    有人会告诉你,使用auto 可以避免这种情况。确实如此,但你永远不会发现这个“错误”,或者const_iterators 的存在。

    【讨论】:

      猜你喜欢
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 2015-06-10
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      相关资源
      最近更新 更多