2013-08-20 34 views
0

好吧,這是一個奇怪的問題,我不確定是否有解決方案。將兩個單獨的std ::列表綁定到彼此

我有兩個列表,每說每個客戶端的一些數據的客戶端列表和列表。我有興趣將這兩個列表保留在兩個獨立的std::list之間,因爲我有一個提供客戶端列表的API,但我不想提供其餘的數據。

然而,由於這兩個列表應針鋒相對,即元素n在所有名單應該是指同一客戶端對齊,我正在尋找一種方式,他們之間這樣一個列表的元素不會鏈接可以在不添加/刪除其他列表中的相應元素的情況下添加/刪除,但仍將它們保留在兩個單獨的列表中,以用於我提到的API目的。

任何想法?

+0

API是否需要返回'常量的std ::列表&'?或者它可以返回其他具有'begin()'和'end()'迭代器的其他東西嗎? – aschepler

+0

[Boost.MultiIndex的(http://www.boost.org/doc/libs/1_54_0/libs/multi_index/doc/index.html)是去這裏 – TemplateRex

+0

@aschepler有'開頭的方式,任何東西() '和'end()'迭代器沒有問題,但在請求時不需要複製或其他操作。 – Subway

回答

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; 
} 
+0

如果'GetClientList'返回'const std :: list &'將會好很多。沒有複製,客戶端代碼將監視「活動」列表,而不是陳舊的副本。 –

+0

謝謝,那會更好 –

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您將使用它的類。