0

好的,这是一个奇怪的问题,我不确定是否有解决方案。

我有两个列表,比如说一个客户列表和每个客户的一些数据列表。我有兴趣将这两个列表保存在两个单独std::list的 s 中,因为我有一个用于提供 clients-list 的 API,但我不想连同它一起提供其余数据。

但是,由于两个列表应该相互对齐,即每个列表中的元素 n 应该引用同一个客户端,我正在寻找一种方法来链接它们,这样一个列表的元素就不能成为添加/删除而不添加/删除另一个列表中的相应元素,但出于我提到的 API 目的,仍将它们保留在两个单独的列表中。

有任何想法吗?

4

2 回答 2

0

如果您要设计界面,我会继续将它们放在一个容器中,但为用户提供只允许访问公共客户端部分的自定义迭代器。 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将使用它的类设为您身边的类。

于 2013-08-20T22:50:37.520 回答
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 回答