2015-02-05 3 views
1

나는 multi_index_container와 index - ordered_unique를 가지고있다. 나는 내 값이 어떻게 든 정렬된다는 것을 안다. 내가 원했던 것은 std :: distance와 같은 O (n) 알고리즘을 사용하지 않고 값의 정확한 순서 색인을 찾는 것입니다.boost :: multi_index_container의 order value index

typedef multi_index_container< 
MyStruct, 
indexed_by< 
    ordered_unique<member< MyStruct, int, &MyStruct::id> >, 
    ordered_non_unique<member< MyStruct, int, &MyStruct::salary> > 
> 
> MyStructsContainer; 

.... 여기

MyStructsContainer myStructsContainer; 

MyStructsContainer::iterator it1 = myStructsContainer.emplace(MyStruct{ 3, 20 }).first; 
MyStructsContainer::iterator it2 = myStructsContainer.emplace(MyStruct{ 1, 100 }).first; 
MyStructsContainer::iterator it3 = myStructsContainer.emplace(MyStruct{ 2, 20 }).first; 

IT1, IT2 및 IT3 RandomAccessIts는 없다. 따라서 색인을 찾는 유일한 방법은 다음과 같습니다.

size_t idx = distance(myStructsContainer.begin(), it1); <--- is there any other and smarter way to find the ordered index?? 
assert(idx == 2); 

다른 방법이 있습니까?

덕분에, 칼린

답변

2

당신은 삽입 순서를 갖고 싶어?

그런 경우 random_access 색인을 추가하면됩니다 (기본값으로 설정했을 수도 있음).

무작위 액세스 반복자에는 O (1) std::distance을 사용할 수 있습니다. 주석으로


UPDATE :

좀 더 효율적인 주문 조회 당신이 요소 내에 순서/순위를 저장하거나 전용 랜덤 액세스 인덱스를 사용 할 수 있습니다합니다. 이 인덱스에 std::distance의 이용 효율이

Index of 1 is 0 
Index of 2 is 1 
Index of 3 is 2 

Live On Coliru

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

struct MyStruct { 
    int id, salary; 
}; 

namespace bmi = boost::multi_index; 
typedef boost::multi_index_container< 
    MyStruct, bmi::indexed_by< 
     bmi::ordered_unique<bmi::tag<struct ById>, bmi::member<MyStruct, int, &MyStruct::id>>, 
     bmi::ordered_non_unique<bmi::tag<struct BySalary>, bmi::member<MyStruct, int, &MyStruct::salary>>, 
     bmi::random_access<bmi::tag<struct RandomAccess> > 
    > > MyStructsContainer; 


int main() 
{ 
    MyStructsContainer c; 
    auto it3 = c.emplace(MyStruct{ 3, 20 }).first; 
    auto it1 = c.emplace(MyStruct{ 1, 100 }).first; 
    auto it2 = c.emplace(MyStruct{ 2, 20 }).first; 

    auto& ra = c.get<RandomAccess>(); 

    // reorder RandomAccess index to match the ById 
    { 
     auto const& idx = c.get<ById>(); 
     std::vector<boost::reference_wrapper<MyStruct const> > tmp(idx.begin(), idx.end()); 
     ra.rearrange(tmp.begin()); 
    } 

    // now you can say: 
    std::cout << "Index of " << (it1->id) << " is " << (std::distance(ra.begin(), bmi::project<RandomAccess>(c, it1))) << "\n"; 
    std::cout << "Index of " << (it2->id) << " is " << (std::distance(ra.begin(), bmi::project<RandomAccess>(c, it2))) << "\n"; 
    std::cout << "Index of " << (it3->id) << " is " << (std::distance(ra.begin(), bmi::project<RandomAccess>(c, it3))) << "\n"; 
} 

인쇄 :

쉽게 rearrange 이러한 인덱스 순서와 일치 할 수 있습니다 당신이 원하는 O(1)

+0

아니요. 방금 문제를 정리하기 위해 수정했습니다. 주문 된 색인이 필요합니다. 그것에 대해 2 은 1입니다. 1 .... – Kiko

+0

@ KalliMan 내 답변을 업데이트했습니다. – sehe

+0

고마워요, 이것은 내 작업의 한 부분으로 작동합니다. 하지만 안타깝게도 나는 emplase 직후 색인을 얻고 싶습니다 .... 같은 방법으로 최적화하기 위해 두 방법을 결합 할 수도 있지만 솔루션이 완벽하지는 않습니다. – Kiko