2012-04-18 83 views
0

的一个子集,我想建立一个多指数具有两个sequenced视图,其中 我可以从只有一个视图移除值。一种多索引,其中一个索引是整个集合

在代码:

#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/sequenced_index.hpp> 

#include <algorithm> 
#include <iterator> 
#include <vector> 

using namespace boost::multi_index; 

typedef multi_index_container< 
    int, 
    indexed_by< 
    sequenced<>, 
    sequenced<> 
    > 
    > container; 

int main() 
{ 
    container c; 
    std::vector<int> 
    // complete 
    data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 
    // only uneven 
    uneven_data; 
    std::copy_if(begin(data), end(data), 
       std::back_inserter(uneven_data), 
       [](int i) { return i % 2 != 0; }); 

    container cont; 
    std::copy(begin(data), end(data), std::back_inserter(cont)); 

    auto& idx0 = cont.get<0>(); 
    auto& idx1 = cont.get<1>(); 
    // remove all uneven from idx1 
    idx1.remove_if([](int i) { return i % 2 == 0; }); 

    // behavior I would like to be true, but now both idx0 and idx1 are 
    // equal to uneven_data 
    assert(std::equal(begin(data), end(data), begin(idx0))); 
    assert(std::equal(begin(uneven_data), end(uneven_data), begin(idx1))); 

    return 0; 
} 

是像这可能与boost::multi_index

+0

没有,我需要过于频繁。 – 2012-04-22 04:06:18

回答

2

否。在boost multi_index_container中,索引作为相同值的单独视图耦合在一起。这是提升multi_index_containers的重要保证。

“的Boost.MultiIndex允许的 multi_index_containers由具有不同 接口元件的同一集合一个或多个索引的规范”(boost multi_index tutorial)。

有两个不同的序列<>指数以两种不同的方式,你可以重新安排顺序,但它们必须包含所有的值。

如果您希望根据布尔谓词查看元素的子集(例如:值是奇数),请考虑使用boost::filter_iterator。这不会尝试在容器中清除值,而是在迭代过程中跳过跳过

或者,可以通过使用multi_index ordered_non_unique索引和适当的key extractor进行排序来获得选择/筛选。

例如,ordered_non_unique索引基于一个key extractor[](int i) { return i % 2; }将放置在奇数和偶数的值在不同的组,因此可使用equal_range获得一个迭代范围的所有奇数值。

+0

它不会是基于谓词的,并且使用已删除的“bool”标记每个值也是不可能的。感谢您提供源代码的答案(即使问题刚刚庆祝了它的第一个生日)。 – pmr 2013-04-20 02:53:58

+0

这些要求可以通过使用[boost intrusive](http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive.html)的定制多索引来解决。使用两个或多个[列表钩子](http://www.boost.org/doc/libs/1_53_0/doc/html/intrusive/list.html),可以使一个对象同时参与两个或更多个序列。 – 2013-04-20 14:50:53

0

如上所述,使用boost intrusive更灵活(基于非谓词)方法。使用两个或更多list hooks可以使一个对象同时参与两个或更多个序列。

#include <boost/intrusive/list.hpp> 
#include <boost/foreach.hpp> 

#include <algorithm> 
#include <memory> 

#include <iostream> 
namespace intr = boost::intrusive; 
template<class Value> 
struct Sequence2 
{ 
    typedef intr::link_mode<intr::auto_unlink> AutoUnlinkMode; 
    typedef intr::list_member_hook<AutoUnlinkMode> SeqHook; 

    struct Node 
    { 
     Node(const Value& i) : value(i) {} 

     operator Value&() 
     { 
      return value; 
     } 

     Value value; 

     SeqHook mainHook; 
     SeqHook hook0; 
     SeqHook hook1; 
    }; 

    typedef intr::member_hook< Node, SeqHook,&Node::mainHook > UsingMainHook; 
    typedef intr::member_hook< Node, SeqHook,&Node::hook0 > UsingSeqHook0; 
    typedef intr::member_hook< Node, SeqHook,&Node::hook1 > UsingSeqHook1; 

    typedef intr::constant_time_size<false> NonConstantTimeSized; 

    typedef intr::list< Node, UsingMainHook, NonConstantTimeSized > NodesList; 
    typedef intr::list< Node, UsingSeqHook0, NonConstantTimeSized > Sequence0; 
    typedef intr::list< Node, UsingSeqHook1, NonConstantTimeSized > Sequence1; 

    NodesList nodes; 
    Sequence0 seq0; 
    Sequence1 seq1; 

    typename NodesList::iterator insert(const Value& item) 
    { 
     Node* node = new Node(item); 

     nodes.push_back(*node); 

     typename NodesList::iterator iter = nodes.end(); iter--; 
     seq0.push_back(*node); 
     seq1.push_back(*node); 
     return iter; 
    } 

    typename Sequence0::iterator iterator0(typename NodesList::iterator iter) 
    { 
     return seq0.iterator_to(*iter); 
    } 
    typename Sequence1::iterator iterator1(typename NodesList::iterator iter) 
    { 
     return seq1.iterator_to(*iter); 
    } 

    //! Erase from both sequences 
    void erase(typename NodesList::iterator at) 
    { 
     nodes.erase_and_dispose(at, std::default_delete<Node>()); 
    } 
    //! Erase from sequence 0 
    void erase(typename Sequence0::iterator at) 
    { 
     Node& n = *at; 

     assert(n.hook0.is_linked()); 
     if(! n.hook1.is_linked()) 
     { 
      seq0.erase_and_dispose(at, std::default_delete<Node>()); 
     } 
     else 
     { 
      seq0.erase(at); 
     } 
    } 
    //! Erase from sequence 1 
    void erase(typename Sequence1::iterator at) 
    { 
     Node& n = *at; 

     assert(n.hook1.is_linked()); 
     if(! n.hook0.is_linked()) 
     { 
      seq1.erase_and_dispose(at, std::default_delete<Node>()); 
     } 
     else 
     { 
      seq1.erase(at); 
     } 
    } 

    ~Sequence2() 
    { 
     nodes.clear_and_dispose(std::default_delete<Node>()); 
    } 
}; 

template< class T > 
void show(Sequence2<T>& mseq, const std::string& comment) 
{ 
    std::cout << comment << "\nseq 0:\t"; 
    BOOST_FOREACH(T& i, mseq.seq0) 
    { 
     std::cout << i << " "; 
    } 
    std::cout << "\nseq 1:\t"; 
    BOOST_FOREACH(T& i, mseq.seq1) 
    { 
     std::cout << i << " "; 
    } 
    std::cout << "\n\n"; 
} 

int main(void) 
{ 
    Sequence2<std::string> mseq; 

    mseq.insert("."); 
    auto iterX = mseq.insert("X"); 
    auto iterY = mseq.insert("Y"); 
    auto iterZ = mseq.insert("Z"); 
    mseq.insert("."); 
    mseq.insert("."); 

    show(mseq, "start"); 

    mseq.seq0.reverse(); 
    show(mseq, "after reverse seq0");  

    mseq.erase(mseq.iterator0(iterY)); 
    show(mseq, "after erase Y in seq0"); 

    // Update a value in both sequences 
    std::string& v = *iterZ; 
    v = "z"; 
    show(mseq, "after modify Z in both"); 


    mseq.erase(iterX); 
    show(mseq, "after erase X in both"); 

    mseq.erase(iterY); 
    show(mseq, "after erase Y in both"); 

    return 0; 
} 

主要生产:

start 
seq 0: . X Y Z . . 
seq 1: . X Y Z . . 

after reverse seq0 
seq 0: . . Z Y X . 
seq 1: . X Y Z . . 

after erase Y in seq0 
seq 0: . . Z X . 
seq 1: . X Y Z . . 

after modify Z in both 
seq 0: . . z X . 
seq 1: . X Y z . . 

after erase X in both 
seq 0: . . z . 
seq 1: . Y z . . 

after erase Y in both 
seq 0: . . z . 
seq 1: . z . . 
相关问题