簡體   English   中英

容器模板參數std :: map或std :: vector

[英]Container template parameter std::map or std::vector

在我的一個項目中,我使用樹實現,其中使用容器C=std::map<K,V>維護每個樹節點的子代列表。 每個樹節點都有一個唯一的名稱密鑰K ,通常為std::string

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!!! 
    }
}

除了以下事實外,該實現對我來說還算不錯,即std :: map不遵守在樹中插入的順序。 對於某些應用程序,我需要保持插入順序,但是對於其他應用程序,需要快速信息重發更為重要。

因此, C必須是任何一種類型

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

要么

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

不,我的TreeNode類的實現存在問題,仍然顯式使用std::map的接口。 特別是,它使用成員函數finderaseinsert ,這些成員函數需要用通用的東西替換,其中兩種容器類型的實現都非常具體。

例如childs.find(key)需要被替換為find(childs.begin(), childs.end(), key) ,每當我插件std::vector實現。

也許還有另一種我不知道的解決方案。 這可能是boost::multi_index ,但是我對此不太確定。

解決我的問題的最簡單方法是什么?

您可以創建專用的重載函數並使用它們

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;
    });
}

使用相同的界面為所需的容器“選擇”創建通用包裝:

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>>;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM