如何使用boost :: ptr_map有效地使用BOOST_FOREACH(字符数/可读性)?
Kristo在他的answer中演示了可以将BOOST_FOREACH与ptr_map一起使用,但它并没有真正省去任何打字(或使我的代码更具可读性),而不是使用迭代器迭代ptr_map:
typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair;
BOOST_FOREACH(IntPair p, mymap) {
int i = p.first;
}
// vs.
boost::ptr_map<int, T>::iterator it;
for (it = mymap.begin(); it != mymap.end(); ++it) {
// doSomething()
}
下面的代码就像我希望的那样。它遵循如何将BOOST_FOREACH与std :: map一起使用的标准方法。不幸的是,这不编译:
boost::ptr_map<int, T> mymap;
// insert something into mymap
// ...
typedef pair<int, T> IntTpair;
BOOST_FOREACH (IntTpair &p, mymap) {
int i = p.first;
}
答案 0 :(得分:16)
作为STL样式容器,指针容器具有可以使用的value_type
typedef:
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/foreach.hpp>
int main()
{
typedef boost::ptr_map<int, int> int_map;
int_map mymap;
BOOST_FOREACH(int_map::value_type p, mymap)
{
}
}
我发现使用容器的typedef可以使代码更容易编写。
此外,您应该尽量避免在boost中使用detail
命名空间的内容,这是一个包含实现细节的提升约定。
答案 1 :(得分:8)
我今天遇到了同样的问题。不幸的是,丹尼尔的建议不适用于对地图的不断引用。在我的例子中,ptr_map是一个类的成员,我想在const成员函数中循环它。借用丹尼尔的例子,这就是我在我的案例中必须做的事情:
#include "boost/ptr_container/ptr_map.hpp"
#include "boost/foreach.hpp"
int main()
{
typedef boost::ptr_map<int, int> int_map;
int_map mymap;
const int_map& mymap_const_ref(mymap);
BOOST_FOREACH(int_map::const_iterator::value_type p, mymap_const_ref)
{
}
}
似乎int_map::const_iterator::value_type
等同于boost::ptr_container_detail::ref_pair<int, const int* const>
。
答案 2 :(得分:6)
使用元组保存自己的输入并提高可读性:
boost::ptr_map<int, T> mymap;
int key;
T * value;
BOOST_FOREACH(boost::tie(key, value), mymap)
{
...
}
答案 3 :(得分:1)
这个用g ++ 4.1.2为我编译的示例代码:
#include "boost/ptr_container/ptr_map.hpp"
#include "boost/foreach.hpp"
int main()
{
boost::ptr_map<int, int> mymap;
typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair;
BOOST_FOREACH(IntPair p, mymap)
{
int i = p.first;
}
return 0;
}
答案 4 :(得分:1)
我使用这个自制模板添加了一个迭代类型,可以通过 BOOST_FOREACH
来处理namspace homebrew
{
template
<
class Key,
class T,
class Compare = std::less<Key>,
class CloneAllocator = boost::heap_clone_allocator,
class Allocator = std::allocator< std::pair<const Key,void*> >
>
class ptr_map :
public boost::ptr_map<Key,T,Compare,CloneAllocator,Allocator>
{
public:
typedef boost::ptr_container_detail::ref_pair<Key,const T* const> const_ref;
typedef boost::ptr_container_detail::ref_pair<Key,T* const> ref;
};
}
我们假设 foo 和 bar 是您最喜欢的两种类型;)
typedef homebrew::ptr_map<foo,bar> Map;
int f( const Map& m )
{
BOOST_FOREACH(Map::const_ref v, m)
{
v.first; // foo
v.second; // const bar* const
}
}
或
int f( Map& m )
{
BOOST_FOREACH(Map::ref v, m)
{
v.first; // foo
v.second; // bar* const
}
}
你必须使用哪一个似乎并不依赖于你在循环中使用它的方式(const或非const),而是依赖于地图的constness!所以以下内容最终会出错...
int f( Map& m )
{
BOOST_FOREACH(Map::const_ref v, m) // can't use const_ref because m isn't const
{
...
}
}
奇怪!不是吗?
对我而言,最重要的是在这里提出的所有这些解决方案中,这是第一个通过Eclipse CDT语法着色正确处理的解决方案(当使用'Code / Problem'语法着色属性时)。
答案 5 :(得分:0)
它应该在没有引用的情况下编译:
BOOST_FOREACH (IntTpair p, mymap)
我认为问题在于地图实际上并不将对象存储为对,而是以第一个元素作为键的树结构,因此BOOST_FOREACH无法获得对对的引用,但它可以创建临时副本之一。
答案 6 :(得分:0)
使用:: value_type将不允许您遍历容器。我使用迭代器引用类型
typedef boost::ptr_map< myKey, myPtrType > MyMap;
MyMap m;
BOOST_FOREACH( MyMap::iterator::reference it, m )
do_something( it.second );
BOOST_FOREACH( MyMap::const_iterator::reference it, m )
do_something_const( it.second );
答案 7 :(得分:0)
最后,我在循环之前声明了迭代变量。
std::pair<std::string, TrailStep*> step;
BOOST_FOREACH(step, m_steps)
{
SAFE_DELETE(step.second);
}
但实际上,应该采用更简单的方法。 (改用D?)
答案 8 :(得分:0)
您可以尝试这种超级酷的方式来迭代地图,ptr或其他方式: https://svn.boost.org/trac/boost/attachment/ticket/3469/foreach_field.hpp
// no typedef needed
BOOST_FOREACH_FIELD((int i)(const T& t), mymap)
// do something with i or t instead of first/second
我不确定它是否适用于模板参数,但也许您只是用于抽象。