インターフェイスを設計する場合は、それらを 1 つのコンテナーに入れますが、パブリック クライアント部分へのアクセスのみを許可するカスタム イテレーターをユーザーに提供します。 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&
とほとんど同じように見えるイテレータ型が 1 つだけ必要になります。const_iterator
Client
ここではオブジェクトのコピーは行われません。ユーザーは、プライベート リスト内にある同じオブジェクトへの参照を取得します。
base()
これは、イテレータ型のパブリック メンバー関数を公開します。これは、悪意のあるユーザーがInternalData
. しかし、知っている、または発見base()
した人は、それを使用するべきではないことを知っているか、認識するようになる必要があります. ただし、これが心配な場合は、プライベートに継承してから、パブリックを除くiterator_adaptor
すべてのパブリックメンバーを手動で再度作成することができます。または(おそらく簡単です)、すべてをプライベートまたは保護してから、それを使用する側のクラスを作成します。 base()
InternalData
friend