class X {
public:
typedef std::list<int> Container;
// (1)
const Container& GetElements() const;
// (2)
Container::iterator ElementBegin();
Container::iterator ElementEnd();
// (3)
CustomIterator GetElementIterator();
private:
Container m_container;
};
我正在寻找一种一致且干净的方法,将封装容器的迭代器提供给调用者。我想出了上面源代码中标记的三个想法。
Container
引用是const,所以您只能使用const_iterator
。返回引用非const是不好的,因为容器本身可以被修改(例如clear()
)。size()
方法(如GetElementCount()
)。可以使用iterator::distance()
,但对于某些容器可能效率低下(重复调用operator++
/ --
来计算距离)。next()
等方法提供自定义迭代器。仍需要自己的size()
方法。我强烈打赌有更好的解决方案,所以如果你知道的话,我会很高兴看到它们。
答案 0 :(得分:2)
(2)和(3)的混合可能就是我要做的事情:
class X {
public :
typedef std::list<int> ElementContainer;
typedef ElementContainer::size_type ElementSizeType;
typedef ElementContainer::iterator ElementIterator;
typedef ElementContainer::const_iterator ConstElementIterator;
ElementIterator elementBegin() { return m_container.begin(); }
ElementIterator elementEnd() { return m_container.end(); }
ConstElementIterator elementBegin() const { return m_container.begin(); }
ConstElementIterator elementEnd() const { return m_container.end(); }
ElementSizeType elementSize() const { return m_container.size(); }
private :
ElementContainer m_container;
};
它仍然留有空间来编写自定义迭代器(通过更改typedef
),但只要容器提供的那些是正常的,就可以使用它们。
答案 1 :(得分:2)
我会改用这些名称:iterator
,const_iterator
,begin
,end
,cbegin
,cend
和{{1} as:
size()
如果你可以使用C ++ 0x,那么使用class X
{
public :
typedef std::list<int>::iterator iterator;
typedef std::list<int>::const_iterator const_iterator ;
iterator begin() { return m_container.begin(); }
iterator end() { return m_container.end(); }
const_iterator cbegin() const { return m_container.begin(); }
const_iterator cend() const { return m_container.end(); }
size_t size() const { return m_container.size(); }
private :
std::list<int> m_container;
};
和m_container.cbegin()
作为:
m_container.cend()
答案 2 :(得分:1)
我想不出更干净的方法;您可以考虑使用
提供访问权限的轻量级(4)解决方案const Container& container() const { return m_container; }
我更喜欢(3),因为容器类型变得完全封装,即您的类型不一定需要包含,您可以更改容器类型而无需重新编译依赖模块。
答案 3 :(得分:1)
当然,最简单的是:
class X {
public:
typedef std::list<int> Container;
Container m_container;
};
但这会使您的class X
过时。
除此之外,如果您真的喜欢您的课程,请添加下一个方法:
Container::const_iterator ElementBegin() const;
Container::const_iterator ElementEnd() const;
int size() const;
答案 4 :(得分:0)
2和3确实不是明显的选择。然而,3写的几乎没用。没有STL算法将使用CustomIterator::next
。对于STL兼容性,您可以写:
// mix of 2 and 3
CustomIterator begin();
CustomIterator end();
并提供CustomIterator
标准operator++
和operator*
答案 5 :(得分:0)
如果您可以使用Boost,那么您可以找到一个库:http://www.boost.org/doc/libs/1_47_0/libs/iterator/doc/index.html 具体来看iterator_facade和iterator_adapter
这是一个做什么的例子 - 它提供了一个std :: vector holder,与STL兼容的迭代器。您可以通过添加其他方法来扩展它,例如operator [],size(),push_back()等。
模板 class VectorHolder { 上市: typedef T value_type;
公共: VectorHolder() :m_values() { }
公共: typedef typename std :: vector :: iterator vector_iterator; typedef typename std :: vector :: const_iterator vector_const_iterator;
class iterator : public boost::iterator_adaptor<iterator, vector_iterator>
{
public:
iterator()
: iterator::iterator_adaptor_()
{
}
iterator(const vector_iterator& it)
: iterator::iterator_adaptor_(it)
{
}
private:
friend class boost::iterator_core_access;
};
class const_iterator : public boost::iterator_adaptor<const_iterator, vector_const_iterator>
{
public:
const_iterator()
: const_iterator::iterator_adaptor_()
{
}
const_iterator(const vector_const_iterator& it)
: const_iterator::iterator_adaptor_(it)
{
}
const_iterator(const iterator& it)
: const_iterator::iterator_adaptor_(it.base())
{
}
private:
friend class boost::iterator_core_access;
};
iterator begin()
{
return iterator(m_values.begin());
}
iterator end()
{
return iterator(m_values.end());
}
const_iterator begin() const
{
return const_iterator(m_values.begin());
}
const_iterator end() const
{
return const_iterator(m_values.end());
}protected:
std::vector<T> m_values;};