0

OK、それは奇妙な問題です。解決策があるかどうかはわかりません。

クライアントのリストと、各クライアントごとのデータのリストなど、2 つのリストがあります。client-list を提供するための API があるため、2 つのリストを 2 つの別々の に保持することに関心std::listがありますが、それと一緒に残りのデータを提供したくありません。

ただし、両方のリストは互いに整列する必要があるため、つまり、各リストの要素 n は同じクライアントを参照する必要があるため、1 つのリストの要素ができないようにそれらの間をリンクする方法を探しています。他のリストの対応する要素を追加/削除せずに追加/削除しましたが、言及した API の目的のために、それらを 2 つの別々のリストに保持します。

何か案は?

4

2 に答える 2

0

本当に簡単なカプセル化を行うことができます

class TwoLists{
  ...
  void addNode(clientstuff a, datastuff b);
  void removeNode(int index);
  const std::list<clientstuff>& GetClientList();
private:
  std::list<clientstuff> clientList; 
  std::list<datastuff> datalist;
}

void TwoLists::addNode(clientstuff a, datastuff b);
{
  //add a to clientList, and add b to dataList
}

void TwoLists::removeNode(int n)
{
  //remove node n from both lists
}

const std::list<clientstuff>& TwoLists::GetClientList()
{
  return clientList;
}
于 2013-08-20T21:57:20.630 に答える
0

インターフェイスを設計する場合は、それらを 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()InternalDatafriend

于 2013-08-20T22:50:37.520 に答える