codingdir logo sitemap sitemap |
Home
PHP
C#
C++
ANDROID
JAVA
JAVASCRIPT
PYTHON

Boost multi_index unqiue index issue


By : , Category : c++

Short answer is you can't do that. As a quick workaround, consider providing some unique string when no key is present, for instance some special character that prevents collision with real keys followed by the position (which is assumed to be unique, right?):

struct PathItem
{
  PathItem(int p,const std::string& k,const std::string& pt):
    Position(p),Key(k),Path(pt){}

  PathItem(int p,const std::string& pt):
    Position(p),Key("!"),Path(pt){Key+=p;}

  int Position;
  std::string Key;
  std::string Path;
};
ReLated :

In the absense of exact use cases, here' some suggestions to model the indices based on what you showed┬╣

struct Product {
int id;
};

struct Category {
int id;
};

struct ProductCategoryRelation {
    int productId;
    int categoryId;
};

namespace bmi = boost::multi_index;

using RelationTable = bmi::multi_index_container<
    ProductCategoryRelation,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct by_product>,
            bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId>
        >,
        bmi::ordered_unique<
            bmi::tag<struct by_category>,
            bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId>
        >
    >
>;

You could also get quite smart with a composite key, which is versatile in ordered_* indexes:

using RelationTable = bmi::multi_index_container<
    ProductCategoryRelation,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct by_product>,
            bmi::composite_key<ProductCategoryRelation,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId>,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId>
            >
        >
    >
>;

Here's a small demo:

Live On Coliru

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/global_fun.hpp>
#include <list>

struct Product {
   int id;
};

struct Category {
   int id;
};

struct ProductCategoryRelation {
    int productId;
    int categoryId;
};

namespace bmi = boost::multi_index;

using RelationTable = bmi::multi_index_container<
    ProductCategoryRelation,
    bmi::indexed_by<
        bmi::ordered_unique<
            bmi::tag<struct compound>,
            bmi::composite_key<ProductCategoryRelation,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::categoryId>,
                bmi::member<ProductCategoryRelation, int, &ProductCategoryRelation::productId>
            >
        >
    >
>;

#include <iostream>
#include <boost/range/iterator_range.hpp>

int main() {
    RelationTable table {
        ProductCategoryRelation { 1, 7 },
        ProductCategoryRelation { 2, 7 },
        ProductCategoryRelation { 3, 7 },
        ProductCategoryRelation { 4, 6 },
        ProductCategoryRelation { 5, 6 },
        ProductCategoryRelation { 6, 6 },
        ProductCategoryRelation { 7, 5 },
        ProductCategoryRelation { 8, 5 },
        ProductCategoryRelation { 9, 5 },
    };

    // find all products in category 6:
    for (auto& rel : boost::make_iterator_range(table.get<compound>().equal_range(6)))
        std::cout << "Product " << rel.productId << " is in category " << rel.categoryId << "
";
}

Prints:

Product 4 is in category 6
Product 5 is in category 6
Product 6 is in category 6

┬╣ I crystal-balled the class names into something "realistic"

Your Get member function returns some const_iterator when it should return Iterator::iterator::const_iterator.

Each index of a multi_index_container has its own iterator type which can't be freely interchanged with those of other indices. So, you have to write something like

employee_set::index<ById>::type::iterator ii = empDataBase.get<ById>().find(2000);

or, if using C++11, simply

auto ii = empDataBase.get<ById>().find(2000);

in the understanding that the type of ii is not the same as that of, say, i. Similarly, the line

empDataBase.erase(ii);

won't work because ii is an iterator of the ById index, whereas empDataBase, whitout further qualification, refers to index #0 (ByName). So you have to write

empDataBase.get<ById>().erase(ii);

or resort to iterator projection.

You can use two containers. Have a boost::ptr_map<> that stores the actual data, and then have a std::vector<> that stores pointers to the nodes of the map.

boost::ptr_map<std::string, Class2> by_field;
std::vector<Class2 const*> by_order;

void insert(Class2* obj) {
    if (by_field.insert(obj->name, obj).second) {
        // on insertion success, also add to by_order
        by_order.push_back(obj);
    }
}

This will give you O(lg n) access in your getFieldByName() function (just look it up in by_field) while also preserving the order of insertion (just look it up in by_order).

Comments


Message :
Login to Add Your Comments .
How to disable registered OpenCL platforms on Windows?
Is Observable broken in Angular 2 Beta 3?
Cross-thread operation not valid when using Invoke
How to pass an IEnumerable or queryable list of properties from Controller to View
Finding numbers after a certain keyword using Python
Pocketsphinx recognizes random phrases in a silence
Passing non-thread-safe objects through thread-safe containers
React scroll nav
BizTalk WCF-BasicHttp Adapter does not allow Empty string for Service Certificate Props
Why property ''cause" of Exception is repeating forever?
Privacy Policy 2017 © codingdir.com All Rights Reserved .