提升zip_iterator忽略const正确性

时间:2017-09-13 13:48:13

标签: c++ boost iterator boost-iterators

在以下代码的main()函数内的for循环中,即使在循环中使用ab,我也可以更改变量const auto&中的变量。有什么方法可以避免这种情况吗?

#include <functional>
#include <iostream>
#include <vector>
#include <string>

#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>

using namespace std;

struct MyClass {
  std::vector<int> a{11, 21, 41};
  std::vector<int> b{1, 2, 4};
  typedef boost::zip_iterator<boost::tuple<std::vector<int>::const_iterator, std::vector<int>::const_iterator>> const_iterator;
  typedef boost::zip_iterator<boost::tuple<std::vector<int>::iterator, std::vector<int>::iterator>> iterator;

  const_iterator begin() const {
    return const_iterator(boost::make_tuple(a.cbegin(), b.cbegin()));
  }
  const_iterator end() const {
    return const_iterator(boost::make_tuple(a.cend(), b.cend()));
  }
  iterator begin() {
    return iterator(boost::make_tuple(a.begin(), b.begin()));
  }
  iterator end() {
    return iterator(boost::make_tuple(a.end(), b.end()));
  }
};


int main(int argc, char** argv)  
{
  MyClass myc;
  for (const auto &ab: myc)
    ab.get<0>() = 66;
  return 0;
}

2 个答案:

答案 0 :(得分:2)

如果迭代const MyClass,那么您将得到所需的编译错误:

for (const auto &ab: const_cast<MyClass const&>(myc))
    ab.get<0>() = 66;

您可以使用std::as_const代替const_cast

for (const auto &ab: std::as_const(myc))
    ab.get<0>() = 66;

这是有效的,因为constbegin的{​​{1}}重载将被调用,并返回end个const迭代器。

答案 1 :(得分:0)

您的问题是myc不是常量,因此您使用myc::iterator而不是myc::const_iterator来迭代它。

然后将ab绑定到通过该迭代器进行间接的结果。 ab.get<0>()将是一个const方法(因为它不会更改ab),但会返回对 -const int的引用。

解决方案是使用std::as_const(myc)(您在const声明中甚至不需要ab

for (auto &ab: std::as_const(myc))
    ab.get<0>() = 66;  // Error.  Cannot write to const object.