我在C ++ 03环境中工作,并且将一个函数应用于地图的每个键都是很多代码:
const std::map<X,Y>::const_iterator end = m_map.end();
for (std::map<X,Y>::const_iterator element = m_map.begin(); element != end; ++element)
{
func( element->first );
}
如果存在key_iterator
,则相同的代码可以利用std::for_each
:
std::for_each( m_map.key_begin(), m_map.key_end(), &func );
那为什么不提供呢?有没有办法让第一种模式适应第二种模式?
答案 0 :(得分:5)
是的,这是一个愚蠢的缺点。但它很容易纠正:你可以编写自己的通用key_iterator类,它可以从map(pair)迭代器构造。我已经完成了它,它只有几行代码,而且制作value_iterator也是微不足道的。
答案 1 :(得分:0)
std::map<K, V>
不需要为键和/或值提供迭代器:这样的迭代器可以根据现有的迭代器轻松构建。嗯,它并不像它应该/可能那么容易,但它肯定是可行的。我知道Boost有一个迭代器适配器库。
真正的问题可能是:为什么标准C ++库不提供迭代器适配器来投影迭代器?简短的回答在我看来:因为,一般来说,你不想修改迭代器来选择访问的属性!您更愿意投影或更一般地转换所访问的值,但仍然保持相同的位置概念。配方不同,我认为有必要将定位的概念(即推进迭代器和测试它们的位置是否有效)与访问给定位置的属性分开。我设想的方法看起来像这样:
std::for_each(m_map.key_pm(), m_map.begin(), m_map.end(), &func);
或者,如果你知道从map的迭代器获得的底层结构是std::pair<K const, V>
(就像std::map<K, V>
的情况一样,但对于类似于关联容器的其他容器则不一定;例如,一个关联容器基于b树将受益于将密钥和值拆分为单独的实体):
std::for_each(_1st, m_map.begin(), m_map.end(), &func);
我的STL 2.0 page是一篇[不完整]的文章,其中详细介绍了我认为应该如何改进标准C ++库算法,包括上面将迭代器分为定位(游标)和属性访问(物业地图)。
答案 2 :(得分:0)
那为什么不提供呢?
我不知道。
有没有办法让第一种模式适应第二种模式?
除了制作“关键迭代器”(参见我的评论和其他答案)之外,你可以在func
周围写一个小包装器,例如:
class FuncOnFirst { // (maybe find a better name)
public:
void operator()(std::map<X,Y>::value_type const& e) const { func(e.first); }
};
然后使用:
std::for_each( m_map.begin(), m_map.end(), FuncOnFirst() );
稍微更通用的包装器:
class FuncOnFirst { // (maybe find a better name)
public:
template<typename T, typename U>
void operator()(std::pair<T, U> const& p) const { func(p.first); }
};
答案 3 :(得分:-1)
key_iterator
或value_iterator
不需要value_type
std::map
是std::pair<const X, Y>
,这就是函数(或函子)所调用的函数由for_each()
运作。单个迭代器没有性能提升,因为pair
聚合在映射使用的二叉树中的基础节点中。
通过std::pair
访问密钥和值几乎不费力。
#include <iostream>
#include <map>
typedef std::map<unsigned, unsigned> Map;
void F(const Map::value_type &v)
{
std::cout << "Key: " << v.first << " Value: " << v.second << std::endl;
}
int main(int argc, const char * argv[])
{
Map map;
map.insert(std::make_pair(10, 20));
map.insert(std::make_pair(43, 10));
map.insert(std::make_pair(5, 55));
std::for_each(map.begin(), map.end(), F);
return 0;
}
给出了输出:
Key: 5 Value: 55
Key: 10 Value: 20
Key: 43 Value: 10
Program ended with exit code: 0