在我的一个项目中,我正在使用树实现,我使用了容器
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
的接口。特别是,它使用需要被泛型替换的成员函数find
,erase
,insert
,其中两种容器类型的实现都非常具体。
例如,每当我插入childs.find(key)
实现时,find(childs.begin(), childs.end(), key)
都需要被std::vector
替换。
也许有另一种解决方案,我不知道。这可能是boost::multi_index
,但我对此非常不确定。
解决我的问题最简单的方法是什么?
答案 0 :(得分: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;
});
}
答案 1 :(得分: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>>;