user1612986
user1612986

Reputation: 1415

Clarification about Boost multi-index container

I am trying to learn about Boost multi-index, may I please seek some help regarding that.

The data looks like as follows:

 index1, index2, index3, index4, value
 alpha   a       1       101     0.5
 alpha   a       1       102     0.6
 ...    ...     ...     ....     ...
 alpha   a       1       120     0.7
 alpha   a       2       101     0.3
 ...    ...     ...     ....     ... 
 alpha   a       2       101     0.3
 alpha   b       1       101     0.3
 ...    ...     ...     ....     ...
 beta   a       1       101     0.7
 ...    ...     ...     ....     ...

Now I have created a structure:

struct data
{
   data(std::string index1,
      std::string index2,
      int index3,
      int index4,
      double value):index1_(index1),index2_(index2),index3_(index3),
      index4_(index4),value_(value){}
    std::string index1_;
    std::string index2_;
    int index3_;
    int index4_;    
    double value_;
};

and also have:

struct index1{};
struct index2{};
struct index3{};
struct index4{};
struct value{}; // I guess i do not need this because this is a data point
                // and not an index. Can someone please comment ?

Next I created a typedef as follows: I am not sure whether to use "ordered_unique" or "ordered_non_unique". Can someone please help.

I have the confusion because the 4-tuple (index1,index2,index3,inde4) is unique co-ordinate pointing to a data value. But for each of them there are repeated occurrence (e.g. for index1 the string "alpha" is repeated several times)

typedef boost::multi_index::multi_index_container<
    data, boost::multi_index::indexed_by<
           boost::multi_index::ordered_unique<boost::multi_index::tag<index1>,boost::multi_index::member<data, std::string,&data::index1_> >,
           boost::multi_index::ordered_unique<boost::multi_index::tag<index2>,boost::multi_index::member<data, std::string,&data::index2_> >,
           boost::multi_index::ordered_unique<boost::multi_index::tag<index3>,boost::multi_index::member<data, int,&data::index3_> >,
           boost::multi_index::ordered_unique<boost::multi_index::tag<index4>,boost::multi_index::member<data, int,&data::index4_> >,

     // not sure if I need the line below. because it is not an index

           boost::multi_index::ordered_unique<boost::multi_index::tag<value>,boost::multi_index::member<data, double,&data::value_> >,
       >
    > data_map;  

Next in the main() I populate the data by looping through each data point and doing an insert like I give below:

 data_map DATA;
 DATA.insert(data(alpha,a,1,101,0.5));

Thereafter, I want to check what is the range of say index4 (i.e. what is the minimum and maximum value). I am trying something like:

    const boost::multi_index::index<data_map,index4>::type& in_index4 = boost::multi_index::get<index4>(DATA);
    int nIndex4 = in_index4.size(); // I do not get the correct size here

Also when I try I do not get the intended results.

    boost::multi_index::index<data_map,index4>::type::const_iterator index_itr=in_index4.begin();
    for(;index_itr!=in_index4.end();index_itr++)
    {
        int xx = (*index_itr).index4_;
    }

Can someone please point out my mistakes and help me with my understanding. Thanks in advance

Upvotes: 2

Views: 540

Answers (1)

sehe
sehe

Reputation: 392911

Q.:

struct value{}; // I guess i do not need this because this is a data point
                // and not an index. Can someone please comment ?

Only create the indexes you use.

Q.: I am not sure whether to use ordered_unique or ordered_non_unique. Can someone please help.

I have the confusion because the 4-tuple (index1,index2,index3,inde4) is unique co-ordinate pointing to a data value. But for each of them there are repeated occurrence (e.g. for index1 the string "alpha" is repeated several times)

You need a unique index on the composite key:

bmi::indexed_by<
    bmi::ordered_unique<
        bmi::composite_key<data,
            bmi::member<data, std::string, &data::index1_>,
            bmi::member<data, std::string, &data::index2_>,
            bmi::member<data, int,         &data::index3_>,
            bmi::member<data, int,         &data::index4_>
        >
    >
>

Q.: Next in the main() I populate the data by looping through each data point and doing an insert like I give below:

May I suggest uniform initialization:

Table table {
    //index1, index2, index3, index4, value
    data {   "alpha", "a", 1, 101, 0.5 },
    data {   "alpha", "a", 1, 102, 0.6 },
    // ...
    data {   "alpha", "a", 1, 120, 0.7 },
    data {   "alpha", "a", 2, 101, 0.3 },
    // ...
    data {   "alpha", "a", 2, 101, 0.3 },
    data {   "alpha", "b", 1, 101, 0.3 },
    // ...
    data {   "beta",  "a", 1, 101, 0.7 },
};

Q.: Thereafter, I want to check what is the range of say index4 (i.e. what is the minimum and maximum value). I am trying something like:

  const boost::multi_index::index<data_map,index4>::type& in_index4 = boost::multi_index::get<index4>(DATA);
  int nIndex4 = in_index4.size(); // I do not get the correct size here

size() returns the number of elements in the container, anyways. You can add the index

bmi::ordered_non_unique<
    bmi::tag<struct index4>, bmi::member<data, int, &data::index4_>
>

and "exploit" the fact that it is ordered:

int min4 = table.get<index4>().begin() ->index4_;
int max4 = table.get<index4>().rbegin()->index4_;

Full Demo

Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <string>
#include <iostream>

struct data
{
    std::string index1_;
    std::string index2_;
    int         index3_;
    int         index4_;
    double      value_;
};

namespace bmi = boost::multi_index;

using Table = bmi::multi_index_container<
    data, bmi::indexed_by<
        bmi::ordered_unique<
            bmi::composite_key<data,
                bmi::member<data, std::string, &data::index1_>,
                bmi::member<data, std::string, &data::index2_>,
                bmi::member<data, int,         &data::index3_>,
                bmi::member<data, int,         &data::index4_>
            >
        >,
        bmi::ordered_non_unique<
            bmi::tag<struct index4>,
            bmi::member<data, int, &data::index4_>
        >
    >
>;

int main() {
    Table table {
        //index1, index2, index3, index4, value
        data {   "alpha", "a", 1, 101, 0.5 },
        data {   "alpha", "a", 1, 102, 0.6 },
        // ...
        data {   "alpha", "a", 1, 120, 0.7 },
        data {   "alpha", "a", 2, 101, 0.3 },
        // ...
        data {   "alpha", "a", 2, 101, 0.3 },
        data {   "alpha", "b", 1, 101, 0.3 },
        // ...
        data {   "beta",  "a", 1, 101, 0.7 },
    };

    // max min index4, exploiting the ordered-ness of the index
    if (!table.empty()) {
        int min4 = table.get<index4>().begin() ->index4_;
        int max4 = table.get<index4>().rbegin()->index4_;

        std::cout << "index4: " << min4 << " - " << max4 << "\n";
    }
}

Prints:

index4: 101 - 120

Upvotes: 2

Related Questions