如果你設計的界面,我會繼續前進,把它們放在一個容器中,但提供的自定義迭代器的用戶只允許訪問公共客戶端部分。 boost::iterator_adaptor
使寫這種迭代器變得容易。
#include "Client.hpp"
#include <list>
#include <boost/iterator_adaptor.hpp>
class ClientList {
public:
class iterator;
class const_iterator;
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end() const;
private:
struct InternalData {
//...
};
struct ClientAndData {
Client client;
InternalData data;
};
typedef std::list<ClientAndData> internal_list_type;
internal_list_type m_clients;
friend class iterator;
friend class const_iterator;
};
class ClientList::iterator
: public boost::iterator_adaptor<
ClientList::iterator, // Derived type for CRTP
ClientList::internal_list_type::iterator // Iter type to encapsulate
Client > // Data type to expose
{
private:
explicit iterator(const base_type& base_iter)
: iterator_adaptor(base_iter) {}
Client& dereference() const { return base()->client; }
friend class ClientList;
// Allow boost to call dereference():
friend class boost::iterator_core_access;
};
class ClientList::const_iterator
: public boost::iterator_adaptor<
ClientList::const_iterator,
ClientList::internal_list_type::const_iterator
const Client >
{
public:
const_iterator(const iterator& iter)
: iterator_adaptor(iter.base()) {}
private:
explicit const_iterator(const base_type& base_iter)
: iterator_adaptor(base_iter) {}
const Client& dereference() const { return base()->client; }
friend class ClientList;
friend class boost::iterator_core_access;
};
inline ClientList::iterator ClientList::begin()
{ return iterator(m_clients.begin()); }
inline ClientList::const_iterator ClientList::begin() const
{ return const_iterator(m_clients.begin()); }
inline ClientList::iterator ClientList::end()
{ return iterator(m_clients.end()); }
inline ClientList::const_iterator ClientList::end() const
{ return const_iterator(m_clients.end()); }
或者,如果你的代碼的用戶應該只得到const Client&
引用,你只需要一個迭代器類型,這看起來大多喜歡上面的const_iterator
類。
沒有Client
對象這裏發生的複製;用戶將獲得對私人列表中相同對象的引用。
這確實暴露了迭代器類型中的公共base()
成員函數,它可能被某人討厭使用以獲得InternalData
。但任何知道或發現base()
的人也應該知道或意識到他們不應該使用它。如果這雖然擔心你,你也許可以繼承iterator_adaptor
私下然後手動使其所有公共成員除了base()
再次公開。或者(可能更容易),使所有InternalData
專用或受保護,然後friend
您將使用它的類。
API是否需要返回'常量的std ::列表&'?或者它可以返回其他具有'begin()'和'end()'迭代器的其他東西嗎? –
aschepler
[Boost.MultiIndex的(http://www.boost.org/doc/libs/1_54_0/libs/multi_index/doc/index.html)是去這裏 – TemplateRex
@aschepler有'開頭的方式,任何東西() '和'end()'迭代器沒有問題,但在請求時不需要複製或其他操作。 – Subway