我有一张地图(std::map<key_t, val_t>
),我想跟踪最新到最近顺序使用的密钥。
这就是我尝试过的,但是我仍然坚持使用循环依赖的声明:
typedef ... key_t;
typedef struct {
...
mru_list_t::iterator mru_it;
} val_t;
typedef std::map<key_t, val_t> foo_map_t;
typedef std::list<foo_map_t::iterator> mru_list_t;
更新程序似乎很简单:
foo_map_t foo_map;
mru_list_t mru_list;
void use(const key_t& key) {
// get the entry corresponding to the key
std::pair<foo_map_t::iterator, bool> r;
r = foo_map.insert(std::make_pair(key, val_t()));
foo_map_t::iterator map_it = r.first;
// the corresponding value
val_t *val = &(*map_it).second;
// did it already exist?
if (!r.second) {
// remove from the mru list
mru_list.erase(val->mru_it);
}
// push to the front of the list
mru_list.push_front(map_it);
val->mru_it = mru_list.begin();
}
我该如何处理? (循环依赖)
我知道我可以转发声明并使用指针代替:
typedef struct _key_t key_t;
typedef struct _val_t val_t;
typedef std::list<std::pair<key_t, val_t> *> mru_list_t;
但这似乎依赖于an undocumented feature。
编辑:或者,我是否需要意识到这无法完成?(并使用未记录的功能,滚动我自己的链接列表,或以其他方式替换其他部分-stl容器?)
答案 0 :(得分:0)
取决于您使用哪种类型的键作为键,并且由于您使用的是单值映射,您可以尝试在列表中存储key_t
,而不是存储迭代器进入std::map
。因为地图每个键只有一个值,所以你仍然可以对该元素进行唯一访问,并且可以摆脱这种可怕的循环依赖问题。
代码看起来像:
typedef std::list<key_t> mru_list_t;
表示列表类型,在use
函数末尾,您需要更改:
mru_list.push_front(map_it);
到
mru_list.push_front(map_it->first);
答案 1 :(得分:0)
我建议您查看Boost Multi Index,它是为同一条数据提供多个索引(因此可以匹配多个订单)。
更具体地说,已经有一个MRU的示例,尽管您现在可能不想查看它,并自己试用该库。
Boost Multi-Index的主要思想是,不是指向元素和可能不同步的多个相互关联的结构,而是将每个元素刻在一个容器单元中,该容器单元被设计为挂钩在多个索引上。
在MRU的例子中,例如,您可以通过将每个“值”铭刻到struct V { value_t value; V* next; }
来自己实现链接列表。