我有一个类似于下一个的容器:
class MySpecialContainer
{
std::vector<std::tuple<InternalType, Type1, Type2>> _vec;
};
其中Type1
和Type2
在容器外部可用,InternalType
仅在容器内使用。要从外部迭代元素,我使用类似于下一个的成员函数:
void MySpecialContainer::iterate(std::function<void(const Type1&, const Type2&)> fun)
{
for(auto& it : _vec)
{
fun(std::get<1>(it), std::get<2>(it));
}
}
正如您所看到的,这种方法有一些限制,例如无法迭代子范围或无法使用非变异std::algorithms
。
考虑MySpecialContainer
元素从逻辑上考虑是不可变的,是否仅为它提供const_iterator
是有意义的?
如果对第一个问题的答案是肯定的,那么......是否更好??
将_vec
分隔为2个容器,一个用于InternalType
,一个用于std::pair<Type1, Type2>
,保持同步,只返回const_iterator
第二个向量
保持现在的矢量并创建一个仅公开const Type1
和const Type2
答案 0 :(得分:3)
一个选项是公开只允许访问元素的某些字段的迭代器,例如:
#include <vector>
#include <tuple>
#include <boost/iterator/transform_iterator.hpp>
struct Type1 {};
struct Type2 {};
struct InternalType {};
class MySpecialContainer
{
typedef std::vector<std::tuple<InternalType, Type1, Type2>> Vec;
Vec _vec;
struct Extractor
{
std::tuple<Type1&, Type2&> operator()(Vec::value_type& t) const {
return std::tie(std::get<1>(t), std::get<2>(t));
}
std::tuple<Type1 const&, Type2 const&> operator()(Vec::value_type const& t) const {
return std::tie(std::get<1>(t), std::get<2>(t));
}
};
public:
typedef boost::transform_iterator<Extractor, Vec::iterator> iterator;
typedef boost::transform_iterator<Extractor, Vec::const_iterator> const_iterator;
iterator begin() { return iterator{_vec.begin()}; }
iterator end() { return iterator{_vec.end()}; }
const_iterator begin() const { return const_iterator{_vec.begin()}; }
const_iterator end() const { return const_iterator{_vec.end()}; }
};
int main() {
MySpecialContainer c;
for(auto x : c) {
}
}
请注意,通过非const迭代器,您仍然可以更新公开的值,因为trasform迭代器返回一个引用元组。
答案 1 :(得分:3)
暴露const迭代器很好。标准中甚至有优先权,因为std::set
有效地做到了这一点。从技术上讲,iterator
和const_iterator
可以是不同的类型,但不允许通过任何类型的迭代器修改元素,因为这可能会破坏set
的不变量。