2016-09-15 4 views
3

누군가가 boost::multi_index을 사용하여 다중 색인지도를 만드는 방법을 자세히 설명해 줄 수 있습니까? 나는 온라인과 많은 예제를 보았지만 이해할 수는 없었다. 여러 개의 int/longs 키로 클래스 개체 포인터를 매핑 할 싶습니다. 누군가 이해할 수있게 도와 줄 수 있습니까?boost/multi_index를 사용/생성하는 방법?

나는 클래스 Xlong long, long, int, int을있는 클래스의 여러 속성을 가지고있다. 속성 long long, long, int, int을 키로 사용하여 -> <에 포인터를 지정하고 X >에 대한 포인터로 매핑합니다.

주어진 속성을 가진 포인터를 찾을 수 있기를 원합니다. 속성 중 일부는 X의 각 개체에 고유하며 일부는 고유하지 않습니다.

+0

int 또는 long을 키로 사용 하시겠습니까? 또는 하나의 int와 하나의 long은 동시에? –

+2

당신은 붙어있는 것을 보여줄 필요가 있습니다. 주어진 유일한 답은 많은 유용한 온라인 예제에 링크하는 것입니다. http://stackoverflow.com/help/mcve를 참조하십시오. – sehe

+0

클래스의 X와 (long long), (long), (int), (int) 클래스의 여러 속성이 있습니다. 나는 <(long long), (long), (int), (int)>를 키로 매핑하여 ->로 저장하려고합니다. – quickdraw

답변

6

Boost.Multi-index은 극도로 복잡한 인터페이스를 제공하는 대신 매우 맞춤화 가능한 인터페이스를 제공하므로 사용자가 고생하는 이유를 쉽게 이해할 수 있습니다.

사용 사례와 일치해야하는 주석이 달린 예제를 제공합니다.

첫째, 우리의 데이터 :

struct X 
{ 
    long long l; // assume unique 
    int i1; // assume unique 
    int i2; // assume non-unique 
    // plus any ohter data you have in your class X 
}; 

다음으로, 우리는 우리가 용기를 가지고 할 각 인덱스에 대해 하나 개의 태그를 준비 할 것입니다. 태그 (인덱스 순서에 액세스 할 수 있습니다) 꼭 필요하지 않은, 그러나 각 인덱스의 이름을 제공하는 것이 더 편리 : 이제

struct IndexByL {}; 
struct IndexByI1 {}; 
struct IndexByI2 {}; 

, 우리는 우리가 함께 컨테이너의 종류를 넣어 필요가 :

using Container = boost::multi_index_container< 
    X*, // the data type stored 
    boost::multi_index::indexed_by< // list of indexes 
    boost::multi_index::hashed_unique< //hashed index over 'l' 
     boost::multi_index::tag<IndexByL>, // give that index a name 
     boost::multi_index::member<X, long long, &X::l> // what will be the index's key 
    >, 
    boost::multi_index::ordered_unique< //ordered index over 'i1' 
     boost::multi_index::tag<IndexByI1>, // give that index a name 
     boost::multi_index::member<X, int, &X::i1> // what will be the index's key 
    >, 
    boost::multi_index::hashed_non_unique< //hashed non-unique index over 'i2' 
     boost::multi_index::tag<IndexByI2>, // give that index a name 
     boost::multi_index::member<X, int, &X::i2> // what will be the index's key 
    > 
    > 
>; 

이제 컨테이너가 생겼습니다. 다음으로, 우리가 그것을 사용하는 방법은 다음과 같습니다

Container c; // empty container 
X x1{...}, x2{...}, x3{...}; // some data 

// Insert some elements 
auto& indexByL = c.get<IndexByL>(); // here's where index tags (=names) come in handy 
indexByL.insert(&x1); 
indexByL.insert(&x2); 
indexByL.insert(&x3); 

// Look up by i1 
auto& indexByI1 = c.get<IndexByI1>(); 
auto itFound = indexByI1.find(42); 
if (itFound != indexByI1.end()) 
{ 
    X *x = *itFound; 
} 

// Look up by i2 
auto& indexByI2 = c.get<IndexByI2>(); 
size_t numberOfHundreds = indexByI2.count(100); 

[Live example]

그리고 지금, 짐승은 일반적으로 작동하는 방법에 대한 몇 가지 산문.

다중 인덱스 컨테이너는 저장할 개체 유형 (사용자의 경우)과 저장된 개체에 액세스하는 데 사용할 수있는 하나 이상의 인덱스를 지정하여 정의합니다. 인덱스는 데이터에 액세스하기위한 인터페이스로 생각하십시오.n으로 생각 (핵심하여 동일한 플러스 쉽게 액세스 랭킹을 기준으로

  • 인덱스 (std::set 또는 std::map 생각)

    • 인덱스 키에 의해 주문에 따라 :

      인덱스는 다른 종류의 수 있습니다 안정된 액세스 순서에 기초하여 키 (std::unordered_set 생각 또는 std::unordered_map)

    • 인덱스에 기초한 해싱 th 요소)
    • 인덱스 (01,234,995 생각 안정 위해 랜덤 액세스를 기반으로)
    • 인덱스 (std::vector 생각)

    핵심 기반 인덱스도 될 수 있습니다 독특한 (같은 std::map), 또는 (std::multimap을 같은) 고유하지 않은.

    컨테이너를 정의 할 때 하나의 템플릿 인수로 가져올 각 인덱스를 boost::multi_index::indexed_by에 전달합니다. 위의 예에서는 3 개의 인덱스를 추가했습니다.

    키를 사용하지 않는 인덱스의 경우 (안정적인 순서 & 임의 액세스) 아무 것도 지정하지 않아도됩니다. 당신은 단지 "나는 그런 지수를 원한다"고 말한다.

    키 기반 인덱스의 경우 데이터에서 키를 얻는 방법도 지정해야합니다. 그것이 핵심 추출기가 작동하는 곳입니다. (이 예에서 boost::multi_index::member의 세 가지 용도입니다.) 기본적으로 각 인덱스에 대해 컨테이너에 저장된 데이터에서 키를 추출하기위한 레서피 (또는 알고리즘)를 제공합니다. 현재 키 추출기은 :

    • 사용 요소 자체 : identity
    • 사용 요소의 데이터 멤버 : member
    • 사용하여 소자의 (일정한) 멤버 함수 : [const_]mem_fun
    • 사용 전역 함수 : 하나에 여러 개의 키 추출기를 결합 global_fun
    • : composite_key

    키 추출기는 포인터를 투명하게 역 참조 할 수 있습니다. 즉, 데이터 요소가 클래스 C에 대한 포인터 인 경우 클래스 C 이상의 키 추출기를 지정할 수 있으며 참조가 자동으로 수행됩니다. 이 속성은 예제에서도 사용됩니다.

    이렇게하면 인덱스가있는 컨테이너가 정의됩니다. 인덱스에 액세스하려면 컨테이너에서 get 멤버 함수 템플릿을 호출합니다. indexed_by의 템플릿 인수 목록에서 순차 번호를 사용하여 색인을 참조 할 수 있습니다. 보다 읽기 쉬운 조작을 위해 각 색인 (또는 그 중 일부 색인)에 태그를 추가 할 수 있습니다. 태그는 인덱스의 순차 번호 대신 get에 대한 템플릿 인수로 해당 유형을 사용할 수있는 임의의 유형 (일반적으로 적절한 이름을 가진 빈 구조)입니다. (이 예에서도 사용됩니다).

    컨테이너에서 인덱스에 대한 참조를 검색하면 인덱스가 해당하는 데이터 구조 (map, hashset, vector 등)와 마찬가지로 사용할 수 있습니다. 해당 색인을 통해 수행 된 변경 사항은 전체 컨테이너에 영향을 미칩니다.

  • +0

    고마워요! 그것은 매우 유용했습니다. 나는 당신이 묘사 한 것과 같은 분리 된 구조로 특성을 가지고 있지 않습니다. 나는 클래스 X 또는 그 부모가 파생 될 다른 클래스의 멤버로서 그 속성을 가질 것이다. 당신의 대답에 변화가 있을까요? – quickdraw

    +0

    @Ram 아니요, 저는 당신이 사용하고있는 구조체 인'X'를 의미했습니다. 나는 그 대답을 분명히 할 것이다. – Angew

    +0

    감사합니다. Angew! 좀 더 명확하게하기 위해 클래스 객체의 포인터가 부모/부모의 부모 클래스에 속한 클래스의 속성에 의해 색인/매핑되도록하고 싶습니다. – quickdraw