boost zip_iterator 忽略 const 正确性
boost zip_iterator ignoring const correctness
在以下代码的main()
函数内的for循环中,即使在循环中使用了const auto&
,我也可以更改变量ab
内的变量。有什么办法可以避免这种情况吗?
#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;
}
如果你遍历 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;
这是有效的,因为 begin
和 end
的 const
重载将被调用,并且它们 return const 迭代器的 zip_iterator
。
你的问题是 myc
不是常量,所以你用 myc::iterator
而不是 myc::const_iterator
.
遍历它
然后将 ab
绑定到通过该迭代器间接访问的结果。 ab.get<0>
() 将是一个 const 方法(因为它不会改变 ab
),但它 returns 是对 non-const 的引用整数
解决方案是使用 std::as_const(myc)
(在 ab
的声明中甚至不需要 const
)。
for (auto &ab: std::as_const(myc))
ab.get<0>() = 66; // Error. Cannot write to const object.
在以下代码的main()
函数内的for循环中,即使在循环中使用了const auto&
,我也可以更改变量ab
内的变量。有什么办法可以避免这种情况吗?
#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;
}
如果你遍历 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;
这是有效的,因为 begin
和 end
的 const
重载将被调用,并且它们 return const 迭代器的 zip_iterator
。
你的问题是 myc
不是常量,所以你用 myc::iterator
而不是 myc::const_iterator
.
然后将 ab
绑定到通过该迭代器间接访问的结果。 ab.get<0>
() 将是一个 const 方法(因为它不会改变 ab
),但它 returns 是对 non-const 的引用整数
解决方案是使用 std::as_const(myc)
(在 ab
的声明中甚至不需要 const
)。
for (auto &ab: std::as_const(myc))
ab.get<0>() = 66; // Error. Cannot write to const object.