2

내 프로젝트 중 하나에서 트리 구현을 사용 중입니다. 여기서 컨테이너 C=std::map<K,V>을 사용하여 각 트리 노드에 대한 하위 목록을 유지 관리합니다. 각 트리 노드에는 K이라는 고유 한 이름 키가 일반적으로 std::string입니다.컨테이너 템플릿 매개 변수 std :: map 또는 std :: vector

template<typename V, template<typename Key=std::string,typename Type=TreeNode<V>,typename ...> typename C> 
class TreeNode { 
    typedef C<std::string, Value> cont_type;  
    typedef V data_type; 

    cont_type childs; 
    data_type value; 

    cont_type::iterator genericFind(const K& k) { 
     // Something generic here!!! 
    } 
} 

이 구현은 표준 : 맵이 트리에 삽입의 순서를 존중하지 않는, 사실 외에 저를 위해 아주 잘했다. 일부 응용 프로그램의 경우 삽입 순서를 유지해야하지만 다른 응용 프로그램의 경우 빠른 정보 재 지정이 더 중요합니다.

는 따라서 C 내가 내 TreeNode 클래스의 구현에 문제가 없음 아직 명시 적으로 std::map의 인터페이스를 사용하여

std::vector<std::pair<K, V>> // keeping insertion order 

또는

std::map<K,V> // fast information retrivial 

유형 중 하나가 될 필요가있다. 특히 멤버 함수 find, erase, insert을 사용합니다. 두 컨테이너 유형의 구현이 매우 구체적 인 일반 항목으로 대체해야합니다.

예를 들어 std::vector 구현을 플러그인 할 때마다 childs.find(key)find(childs.begin(), childs.end(), key)으로 바꿔야합니다.

아마도 내가 알지 못하는 다른 해결책이있을 수 있습니다. 아마 boost::multi_index 일지 모르지만 나는 이것에 대해 확실히 확신하지 못합니다.

내 문제를 해결하는 가장 쉬운 방법은 무엇일까요?

+0

프리 페치로 인해 벡터가 매우 빨라질 수 있습니다. "천천히"하는 것으로 그들을 해고하지 마십시오. 나는 (과학만을 위해) 벡터 구현을하고 성능 차이를 측정 할 것을 제안한다. – Hayt

+0

다음과 같은 것이 도움이 될 수 있습니다. http://codereview.stackexchange.com/a/59999/42409 – Deduplicator

+0

하나는 시퀀스 컨테이너이므로 다른 컨테이너는 대칭에 가까운 것을 찾기를 기대합니다. 그럼에도 불구하고 빠른 검색이 실제로 메뉴에있는 경우 연관 컨테이너에 대해 'unordered_map'을 할인하지 마십시오. 가치가있는 가치. 당신의'지우기 '요구 사항이 아니라면, 나는 값의 벡터와 벡터를 벡터 인덱스에 매핑하는 맵 (당신이 선택한 종류)을 유지할 것을 제안했을 것입니다.하지만'지우기'는 수영장. – WhozCraig

답변

3

전용 과부하 기능을 생성하여 사용하십시오.

template <typename Key, typename V> 
auto my_find(std::map<Key, V>& m, const Key& key) 
{ 
    return m.find(key); 
} 

template <typename Key, typename V> 
auto my_find(std::vector<std::pair<Key, V>>& v, const Key& key) 
{ 
    return std::find_if(v.begin(), v.end(), [&](const auto& p) { 
     return p.first == key; 
    }); 
} 
+0

이 솔루션은 약간의 수정 후 나를 위해 작동합니다. 많은 감사합니다. 삽입과 동일한 작업을 수행해야했지만 지우는 일반적인 방법을 발견했습니다. 불행히도 const 및 non-const 비헤이비어에 대해 네 가지 find 함수가 필요했습니다. – Aleph0

+0

@FrankSimon : 필자는 find의 3 가지 기능으로 축소 할 수 있습니다. [Demo] (http://coliru.stacked-crooked.com/a/38ab9aca2e7a262b). – Jarod42

+0

와우! 나는 이것을 소화 할 시간이 필요해. :-) – Aleph0

2

동일한 인터페이스를 원하는 용기 "선택"에 대한 일반적인 래퍼를 만듭니다

template <typename TKey, typename TValue> 
class my_map_wrapper 
{ 
private: 
    std::map<TKey, TValue> _map; 

public: 
    // Same interface as 'my_vector_wrapper'. 
    template <typename TEKey, typename TEValue> 
    void emplace(TEKey&& key, TEValue&& value) 
    { 
     _map.emplace(std::make_pair(std::forward<TEKey>(key), 
            std::forward<TEValue>(value))); 
    } 

    // ... 
}; 


template <typename TKey, typename TValue> 
class my_vector_wrapper 
{ 
private: 
    std::vector<std::pair<TKey, TValue>> _vec; 

public: 
    // Same interface as 'my_map_wrapper'. 
    template <typename TEKey, typename TEValue> 
    void emplace(TEKey&& key, TEValue&& value) 
    { 
     _vec.emplace_back(std::forward<TEKey>(key), 
          std::forward<TEValue>(value)); 
    } 

    // ... 
}; 

을 템플리트 래퍼 자체에 대한 당신의 트리 노드 클래스 :

template <typename TWrapper> 
class TreeNode 
{ 
private: 
    TWrapper _container; 

public: 
    // Use "uniform" container interface... 
}; 

이제 편리한 타입 별칭을 정의 할 수 있습니다 사용자 코드의 컨테이너 중에서 선택하는 방법 :

template <typename TKey, typename TValue> 
using MapTreeNode = TreeNode<my_map_wrapper<TKey, TValue>>; 

template <typename TKey, typename TValue> 
using VectorTreeNode = TreeNode<my_vector_wrapper<TKey, TValue>>; 
+0

좋은 지적. 그러나 my_map_wrapper의 두 번째 템플릿 매개 변수는 TValue가 아니라 TreeNode <...>이어야합니다. 이제 나는 다시 길을 잃는다. – Aleph0

+0

많은 도움에 감사드립니다. Jarod42가 제안한 접근 방식은 제 종류의 수업에 더 적합했습니다. 네 생각은 좀 더 일반적인 것 같아. 하지만이 두 가지 전문 분야가 필요합니다. – Aleph0

+0

당신은 환영합니다 :) –