C++ 如何将BOOST_FOREACH与BOOST::ptr_映射一起使用?

C++ 如何将BOOST_FOREACH与BOOST::ptr_映射一起使用?,c++,boost,C++,Boost,如何将BOOST_FOREACH(字符数/可读性)与BOOST::ptr_映射有效地结合使用 Kristo在他的著作中演示了将BOOST_FOREACH与ptr_映射结合使用是可能的,但与使用迭代器在ptr_映射上进行迭代相比,它并没有真正为我节省任何输入(或使我的代码更具可读性): typedef boost::ptr_container_detail::ref_pair<int, int* const> IntPair; BOOST_FOREACH(IntPair p, myma

如何将BOOST_FOREACH(字符数/可读性)与BOOST::ptr_映射有效地结合使用

Kristo在他的著作中演示了将BOOST_FOREACH与ptr_映射结合使用是可能的,但与使用迭代器在ptr_映射上进行迭代相比,它并没有真正为我节省任何输入(或使我的代码更具可读性):

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()
}
typedef boost::ptr_container_detail::ref_pair IntPair;
BOOST_FOREACH(IntPair p,mymap){
int i=p.优先;
}
//vs。
boost::ptr_map::迭代器;
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;
}
boost::ptr_-map-mymap;
//在mymap中插入一些内容
// ...
typedef对IntTpair;
BOOST_FOREACH(IntTpair&p,mymap){
int i=p.优先;
}

它应该在没有引用的情况下编译:

BOOST_FOREACH (IntTpair p, mymap)

我认为问题在于,映射实际上并没有将对象存储为对,而是存储为以第一个元素为键的树结构,因此BOOST_FOREACH无法获取对的引用,但它可以创建对的临时副本。

使用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;
}
#包括“boost/ptr_container/ptr_map.hpp”
#包括“boost/foreach.hpp”
int main()
{
boost::ptr_map mymap;
typedef boost::ptr_container_detail::ref_pair IntPair;
BOOST_FOREACH(IntPair p,mymap)
{
int i=p.优先;
}
返回0;
}

作为STL样式的容器,指针容器有一个
值\u type
类型定义,您可以使用:

#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)
    {
    }
}
#包括
#包括
int main()
{
typedef boost::ptr_映射int_映射;
国际地图我的地图;
BOOST_FOREACH(int_map::value_type p,mymap)
{
}
}
我发现对容器使用typedef可以使代码更容易编写


另外,您应该尽量避免在boost中使用
detail
名称空间的内容,它们包含实现细节是boost的惯例。

我今天遇到了同样的问题。不幸的是,丹尼尔的建议在不断地引用地图的情况下是行不通的。在我的例子中,ptr_映射是一个类的成员,我想在const member函数中循环它。借用Daniel的例子,这是我在我的情况下必须做的:

#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)
    {
    }
}
#包括“boost/ptr_container/ptr_map.hpp”
#包括“boost/foreach.hpp”
int main()
{
typedef boost::ptr_映射int_映射;
国际地图我的地图;
常数int_图和mymap_常数参考(mymap);
BOOST\u FOREACH(int\u map::const\u迭代器::value\u type p,mymap\u const\u ref)
{
}
}

似乎
int\u map::const\u iterator::value\u type
相当于
boost::ptr\u container\u detail::ref\u pair
,使用::value\u 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 );
typedef boost::ptr_mapMyMap;
MyMap m;
BOOST_FOREACH(MyMap::iterator::reference it,m)
做点什么(第二次);
BOOST_FOREACH(MyMap::const_iterator::reference it,m)
持续做某事(第二次);

最后,我在循环之前声明了迭代变量

std::pair<std::string, TrailStep*> step;
BOOST_FOREACH(step, m_steps)
{
    SAFE_DELETE(step.second);
}
std::配对步骤;
每一步的升压(步数,m步数)
{
安全删除(第二步);
}

但事实上,应该有一个更简单的方法。(改用D?

我使用这个自制模板,它添加了一个迭代类型,可以由BOOST\u 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;
  };
} 
您必须使用哪一个似乎并不取决于您在循环中使用它的方式(常量或非常量),而是取决于地图的常量!!因此,以下内容将以错误告终

int f( Map& m )
{
  BOOST_FOREACH(Map::const_ref v, m)  // can't use const_ref because m isn't const
  {
    ...
  }
}
奇怪!不是吗


对我来说,最重要的是,在这里提出的所有解决方案中,这是第一个通过Eclipse CDT语法着色(在使用“代码/问题”语法着色属性时)正确处理的解决方案。

您可以尝试这种超级酷的方法来迭代地图、ptr或其他:


我不确定它是否适用于模板参数,但可能您只是为了抽象而使用它。

通过使用元组保存键入并提高可读性:

boost::ptr_map<int, T> mymap;
int key;
T * value;
BOOST_FOREACH(boost::tie(key, value), mymap)
{
    ...
}
boost::ptr_-map-mymap;
int键;
T*值;
BOOST_FOREACH(BOOST::tie(键,值),mymap)
{
...
}

谢谢你,克里斯托,这也是我最终想到的。然而,对于这个,它必须在typedef中写很多东西,以至于它不再是(ptr_map::iterator it=mymap.begin();it!=mymap.end();++it){}标准的真正缩写了……我同意。我很想知道是否有一种更短(更好?)的方式来编写typedef。你也必须考虑你的同事。他们中有多少人会说,“你写了一个疯狂的typedef只是为了让你使用BOOST_FOREACH?只要写一个normal for循环就可以了。”:)这个编译过吗?通过查看
元组
ptr_容器
的历史代码,我不禁得出这样的结论:它不可能(而且任何尝试都失败了)。看见
int f( Map& m )
{
  BOOST_FOREACH(Map::const_ref v, m)  // can't use const_ref because m isn't const
  {
    ...
  }
}
// no typedef needed
BOOST_FOREACH_FIELD((int i)(const T& t), mymap)
   // do something with i or t instead of first/second
boost::ptr_map<int, T> mymap;
int key;
T * value;
BOOST_FOREACH(boost::tie(key, value), mymap)
{
    ...
}