【发布时间】:2014-06-29 15:13:29
【问题描述】:
我正在寻找一种简单的方法来为 C++11 中的 map 的值创建迭代器。
这个方法应该简单和透明:简单是因为它应该易于实现,透明是因为客户端不应该知道值来自映射,而不是集合。
这个问题已经被问过好几次了。其中许多问题早于 C++11 并使用了我不想使用的 boost。有些并不简单,John Ahlgren 的解决方案在这里,http://john-ahlgren.blogspot.com/2013/10/how-to-iterate-over-values-of-stdmap.html,例如需要一页代码来编写自定义迭代器。
其他的不是透明的,也就是说,很明显可以写:
map<string,foo> mymap;
for (auto it=mymap.begin();it!=mymap.end();++it){
Foo val= it->second;
...
}
但是,我不想这样做,因为我不希望客户端知道数据表示。
问题如下。
我有一堆用长“键”唯一索引的对象。有时我想操纵这些对象的集合。其他时候我想检索一个给定键的对象。
我不能直接使用“set”类有几个原因,其中主要是它不存储可变实例,并且这些实例必须是可变的(显然,除了键)。
所以,我决定将我所有的对象存储在一个巨大的全局哈希表中:
map<long,Foo> all_the_objects;
然后我根本不使用set<Foo>。相反,我使用 set<long> 并使用适配器来模拟一组 Foo,即,
class SetOfFoo{
private: set<long> theKeys;
public:
void insert(const & Foo);
size_t size() return theKeys.size();
bool is_member(const & Foo)
{return theKeys.find(Foo.key)
!= theKeys.end;}
Foo & insert(const & Foo val){
long key=val.key;
all_the_objects[key]=val;
return all_the_objects[key];
}
...::iterator begin() {???}
}
换句话说,SetOfFoo 类的客户端不知道或不需要知道 SetOfFoo 是作为键集实现的。
我也不能自己在适配器类中创建一个 Vector,因为不能将引用存储在 C++ 集合中。
真的不可能用一种简单、透明的方式来迭代 map 值吗?我很难相信,因为这是一个非常普遍的需求,而且在我见过的每一种具有哈希表的语言中都是微不足道的。我只是不明白这有多难。
【问题讨论】:
-
如果我这样做,我会使用
for(auto const& value: mymap | boost::adaptors::map_values) {/*...*/}。这使用来自Boost.Range的boost::adaptors::map_values。 -
旁注:
std::map使用树表示,不是哈希表。如果您确实需要 O(1) 查找,请使用std::unordered_map。 -
我不想使用 Boost。我认为 STL 取代了 Boost,无论如何,我在这段代码中已经有多个巨大的东西,我在编译和链接它时遇到了足够多的麻烦。我不会为这样的小事添加一个全新的库!
-
因此您需要一个简单、易用、通用的解决方案。有人写了一个简单易用的通用解决方案,但你不想使用它......
-
这根本不是地图的基本功能,因为它可以在地图之上实现而不会影响性能。提供关于在哈希表中放置元素的提示的能力是基本的,因为类的外部用户在不修改类本身的内部细节的情况下无法实现这一点。
标签: c++ c++11 map iterator std