将 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#include <boost/foreach.hpp>
一旦我添加该解决方案完美运行。奇怪的是,您没有收到错误提示 BOOST_FOREACH 未声明。
有趣的是,typedef
是必要的,因为(至少在 g++ 4.8.5 中)忽略它会使预处理器认为三个参数已传递给 BOOST_FOREACH
而不是只有两个(由于std::map
的模板参数中的逗号)。【参考方案2】:
这是一个旧线程,但有一个更方便的解决方案。
boost 具有对迭代器范围执行转换的“范围适配器”的概念。对于这个确切的用例(迭代映射键或值)有特定的范围适配器:boost::adaptors::map_values
和 boost::adaptors::map_keys
。
所以你可以像这样迭代地图值:
BOOST_FOREACH(int& size, mmap | boost::adaptors::map_values)
++size;
更多信息here。
【讨论】:
此解决方案需要包含<boost/range/adaptor/map.hpp>
。【参考方案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 一起使用的主要内容,如果未能解决你的问题,请参考以下文章