在C++中迭代std::map的键/值

5
我的问题是对这个问题的略微概括。为了讨论,我将专注于遍历映射键。我想要一个通用的辅助函数key_iterator,它接受一个映射迭代器并返回一个映射键迭代器。例如,以下代码:
#include "key_iterator.hpp"
#include <algorithm>
#include <iostream>
#include <iterator>
#include <map>

int main(int argc, char** argv)
{
    std::map<std::string, int> m;
    m["One"] = 1;
    m["Two"] = 2;
    std::copy(key_iterator(m.begin()), key_iterator(m.end()), std::ostream_iterator<std::string>(std::cout, " "));
    return 0;
}

应该生成以下输出:
One Two

正如上述问题的解决方案所建议的那样,boost::transform_iterator似乎是实现key_iterator的合适起点。我有一个半成品的解决方案,key_iterator.hpp看起来像这样:

#pragma once

#include <functional>
#include <map>
#include <boost/iterator/transform_iterator.hpp>

template <typename Key, typename Value>
class KeyGetter : public std::unary_function<std::pair<Key,Value>, Key>
{
public:
    const Key& operator()(const std::pair<Key,Value>& p) const {return p.first;}
};

template<typename Key, typename Value>
boost::transform_iterator<KeyGetter<Key,Value>, typename std::map<Key,Value>::iterator>
key_iterator(typename std::map<Key,Value>::iterator itr)
{
    return boost::make_transform_iterator<KeyGetter<Key,Value>, typename std::map<Key,Value>::iterator>(itr, KeyGetter<Key,Value>());
}

但是使用这种实现方式时,键和值类型不能自动推断,我需要手动提供它们才能使其编译:

std::copy(key_iterator<std::string,int>(m.begin()), key_iterator<std::string,int>(m.end()), std::ostream_iterator<std::string>(std::cout, " "));

有没有想法可以让这个按照我想要的方式运行?

类似问题:https://dev59.com/VXVD5IYBdhLWcg3wDG_l#110228 - Nicolae Dascalu
boost.range 的 map_keys 有什么问题吗?http://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/map_keys.html - Cubbi
@dnikku - 感谢你提供了一些不错的建议,但是没有一个能像key_iterator那样做到我想要的,也就是给定一个map“iterator”,返回一个map“key iterator”。 - dsmith
@Cubbi - 谢谢!我不知道map_keys。但我仍然有兴趣看看如何修改我的函数模板以提供模板参数的自动推导。 - dsmith
1个回答

7

试试这个:

template <typename Iter>
struct KeyGetter : std::unary_function<typename Iter::value_type,
        typename Iter::value_type::first_type>
{
    const typename Iter::value_type::first_type& operator()
            (const typename Iter::value_type& p) const
        { return p.first; }
};

template<typename Iter>
boost::transform_iterator<KeyGetter<Iter>, Iter> key_iterator(Iter itr)
{
    return boost::make_transform_iterator<KeyGetter<Iter>, Iter>
        (itr, KeyGetter<Iter>());
}

这个想法是在调用函数时,应直接对其参数进行模板化,以避免显式指定模板参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接