3

I'm working with boost::multi_index container. Basically it consists of some data plus the information if the data set information are complete (when an item is added to the container, information are not completed yet). The container is sequenced because I must know the order items were added to the container.

#include <boost/multi_index_container.hpp>    
#include <boost/multi_index/hashed_index.hpp>    
#include <boost/multi_index/ordered_index.hpp>    
#include <boost/multi_index/member.hpp>    
#include <boost/multi_index/composite_key.hpp>    
#include <boost/multi_index/sequenced_index.hpp>    
#include <boost/multi_index/key_extractors.hpp>    


struct indexed_struct    
{    
    unsigned int identifier;    
    unsigned int iterationFinished;    

    indexed_struct():    
        identifier(0), iterationFinished(0){}

    indexed_struct(unsigned int identifier, unsigned int iterationFinished):    
        identifier(identifier), iterationFinished(iterationFinished){}



    friend std::ostream& operator<<(std::ostream& os,const indexed_struct& c)    
    {    
        os<<c.identifier<<std::endl;    
        return os;    
    }
};

struct identifierTag {};    
struct finishedTag {};


typedef boost::multi_index::multi_index_container<    
    indexed_struct,    
        boost::multi_index::indexed_by<boost::multi_index::sequenced<>,    
            boost::multi_index::ordered_unique<boost::multi_index::tag<identifierTag>,    
            BOOST_MULTI_INDEX_MEMBER(indexed_struct, unsigned int, identifier)    
        >,    
        boost::multi_index::ordered_non_unique<boost::multi_index::tag<finishedTag>,    
            BOOST_MULTI_INDEX_MEMBER(indexed_struct, unsigned int, iterationFinished)    
        >    
    >    
> cmm_iteration_table;



void setFinished(cmm_iteration_table& table, unsigned int iteration)    
{    
    cmm_iteration_table::index<identifierTag>::type::iterator it;    
    it = table.get<identifierTag>().find(iteration);    
    indexed_struct mod(*it);    
    mod.iterationFinished = 1;    
    table.get<identifierTag>().replace(it, mod);

}


void main()    
{    
    cmm_iteration_table table;

    //add some items with iterationFinished set to 0    
    table.push_back(indexed_struct(30,0));    
    table.push_back(indexed_struct(20,0));    
    table.push_back(indexed_struct(40,0)); 

    //now set iterationFinished to 1 in a random order
    setFinished(table, 30);    
    setFinished(table, 40);    
    setFinished(table, 20);

    //try to get iterator for iterationFinished == 1 and sequenced
    //30-20-40 as added

    std::copy(table.get<finishedTag>().equal_range(1).first, table.get<finishedTag>().equal_range(1).second, std::ostream_iterator<indexed_struct>(std::cout)); //outputs 20,40,30 but 30, 20, 40 is intended

    std::copy(table.begin(), table.end(), std::ostream_iterator<indexed_struct>(std::cout)); //outputs 30,20,40, but would also output items where iterationFinished == 0

}

I would like to obtain an iterator pair iterating through the sequenced items where iterationFinished is set to 1.

First std::copy is with index to the iterationFinished flag but the order is not correct (in the meaning that i wanted the order to be as items where pushed into the container)

Second std::copy gives correct order, but woul also print items with iterationFinished == 0.

Any hints?

1 Answers1

1

Try using boost::filter_iterator

something like this:

struct is_finished 
{
    bool operator()(indexed_struct const& x) { return x.iterationFinished; }
};

typedef cmm_iteration_table::index<identifierTag>::type::iterator iterator_type;

iterator_type it, ite;    
it = table.get<identifierTag>().begin();
ite = table.get<identifierTag>().end();

typedef boost::filter_iterator<is_finished, iterator_type> filter_iter_t;
filter_iter_t f_it(is_finished(), it, ite), f_ite(is_finished(), ite, ite);

std::copy(f_it, f_ite, std::ostream_iterator<indexed_struct>(std::cout));
ronalchn
  • 12,225
  • 10
  • 51
  • 61
Alex I.
  • 11
  • 2