为什么std :: map没有提供key_iterator和value_iterator?

时间:2013-11-17 11:26:37

标签: c++ iterator standard-library stdmap c++03

我在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 );

那为什么不提供呢?有没有办法让第一种模式适应第二种模式?

4 个答案:

答案 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_iteratorvalue_iterator不需要value_type std::mapstd::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