将 BOOST_FOREACH 与 std::map 一起使用

Posted

技术标签:

【中文标题】将 BOOST_FOREACH 与 std::map 一起使用【英文标题】:using BOOST_FOREACH with std::map 【发布时间】:2010-10-22 04:19:27 【问题描述】:

我想使用 BOOST_FOREACH 遍历 std::map 并编辑值。我不太明白。

typedef std::pair<int, int> IdSizePair_t;
std::map<int,int> mmap;    
mmap[1] = 1;
mmap[2] = 2;
mmap[3] = 3;
BOOST_FOREACH( IdSizePair_t i, mmap )
    i.second++;
// mmap should contain 2,3,4 here

当然,这不会改变任何事情,因为我没有通过引用进行迭代。所以我用这一行代替(根据 Boost 文档中的示例):

BOOST_FOREACH( IdSizePair_t &i, mmap )

我得到编译器错误:

error C2440: 'initializing' : 
cannot convert from 'std::pair<_Ty1,_Ty2>' to 'IdSizePair_t &'
    with
    [
        _Ty1=const int,
        _Ty2=int
    ]

有什么建议吗?

【问题讨论】:

你用的是什么编译器?我在VS2008上试过你的代码,它工作正常。我也测试了 hvint 的 answer 并且它有效。如果这很重要,我正在使用 boost 1.36。 你可能忘记了 & ?没有它,它会复制另一对,然后常量就无关紧要了。 【参考方案1】:

问题在于该对的第一个成员,它应该是 const。试试这个:

typedef std::map<int, int> map_t;
map_t mmap;  
BOOST_FOREACH( map_t::value_type &i, mmap )
    i.second++;

【讨论】:

谢谢,hvint。做到了。另外(在阅读了您的评论后)我意识到解决它的另一种方法是将原始代码的第一行更改为: typedef std::pair IdSizePair_ty; (这允许我通过引用进行迭代) kmote,是的,实际上这就是我在我的回答中提出的(当我看到 hvint one's 时我删除了它)。另外,你知道它为什么会这样吗?如果您需要解释,我会取消删除我的。 回答***.com/questions/795443/…“我得到一个编译错误:错误C2065:'i':未声明的标识符”我得到了同样的错误,直到我意识到我没有#include &lt;boost/foreach.hpp&gt;一旦我添加该解决方案完美运行。奇怪的是,您没有收到错误提示 BOOST_FOREACH 未声明。 有趣的是,typedef 是必要的,因为(至少在 g++ 4.8.5 中)忽略它会使预处理器认为三个参数已传递给 BOOST_FOREACH 而不是只有两个(由于std::map 的模板参数中的逗号)。【参考方案2】:

这是一个旧线程,但有一个更方便的解决方案。

boost 具有对迭代器范围执行转换的“范围适配器”的概念。对于这个确切的用例(迭代映射键或值)有特定的范围适配器:boost::adaptors::map_valuesboost::adaptors::map_keys

所以你可以像这样迭代地图值:

BOOST_FOREACH(int& size, mmap | boost::adaptors::map_values)
 
    ++size;

更多信息here。

【讨论】:

此解决方案需要包含&lt;boost/range/adaptor/map.hpp&gt;【参考方案3】:

另一种选择是使用 BOOST_FOREACH_PAIR,请在此处查看我的答案:

BOOST_FOREACH & templates without typedef

【讨论】:

我喜欢 BOOST_FOREACH_PAIR 的外观,但我没有看到任何官方引用它,而且它不在我使用的 1.46 版本中。它曾经被包含在官方版本中吗? 那只是一个自制的宏——它从未在 boost 中实现。在svn.boost.org/trac/boost/ticket/3469 中以 wontfix 结尾(支持基于 C++11 范围的循环)【参考方案4】:

从 C++11 开始考虑使用 auto 关键字:

std::map<int,int> mmap;    
mmap[1] = 1;
mmap[2] = 2;
mmap[3] = 3;

BOOST_FOREACH(auto& mpair, mmap)
    mpair.second++;

//mmap will contain 2,3,4 here

【讨论】:

以上是关于将 BOOST_FOREACH 与 std::map 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

用BOOST_FOREACH简化遍历操作

修改 BOOST_FOREACH 中向量的内容

BOOST_FOREACH宏强制方法退出Visual Studio命名空间

使用boost迭代xml文件

在迭代期间同时修改映射

Boost.Thread 还是只是::thread?