取消引用迭代器作为boost :: bind复合链的一部分

时间:2013-04-10 16:55:11

标签: c++ boost bind composite dereference

我正在尝试使用bind来生成一个函数:

  • 收到地图m
  • 返回m.begin() - >第一个

为此我试图使用boost :: bind:

typedef map<int,int>::const_iterator (map<int,int>::*const_begin_end) () const;
bind(&pair<const int,int>::first, bind(static_cast<const_begin_end>(&map<int, int>::begin), _1));

这不起作用,因为开始的结果需要被取消引用。我想像

bind(&pair<const int,int>::first, bind(&operator*, bind(static_cast<const_begin_end>(&map<int, int>::begin), _1)));

但由于没有全局运算符*,这不起作用。

问题:

  • 使用boost :: bind复合链是否可以实现这一目标?怎么样?
  • 更容易阅读的替代方案?

2 个答案:

答案 0 :(得分:1)

你可以使用成员函数指针调用bind,而成员运算符只是成员函数:

 const_begin_end pBegin = &map<int,int>::begin;
 x = bind(&std::pair::first, 
    bind(&std::map<int, int>::const_iterator::operator*, 
      bind(pBegin, _1)
    );

但是说真的,你也可以写一个合适的函数来做你需要的而不是那个难以理解的boost.bind混乱(你能说“可维护性”吗?)。

因此,对于C ++ 03,一个函数:

template <class Map>
typename Map::key_type keyBegin(Map const& m)
{ 
  return m.begin().first;
}

或C ++ 03仿函数(您可以在函数内部进行定义)

struct KeyBegin
{
  typedef std::map<int, int> IntMap;
  int operator()(IntMap const& m) {
    return m.begin().first;
  }
};

或C ++ 11 lambda(比绑定狂欢更可读):

auto keyBegin = [](std::map<int, int> const& m) -> int {
  return std::begin(m).first;
};

答案 1 :(得分:1)

我强烈推荐Boost.Phoenix,这是我在C ++ 03中动态编写仿函数的首选库。它是Boost.Bind的优秀替代品 - 该图书馆正在显示它的年龄。

例如,Phoenix让我们在其仿函数上使用运算符来表示调用仿函数时该运算符的实际用法。因此arg1 + arg2是一个函子,它返回前两个操作数的总和。这大大减少了bind噪音。第一次尝试可能看起来像:

bind(&pair<const int, int>::first
     , *bind(static_cast<const_begin_end>(&map<int, int>::begin), arg1)) )

LWS demo

但菲尼克斯的另一个优点是,它配备了一些电池。在我们的例子中,我们对<boost/phoenix/stl/container.hpp>非常感兴趣,因为这包括一些熟悉的容器操作的懒惰版本,包括begin。这在我们的案例中非常方便:

// We don't need to disambiguate which begin member we want anymore!
bind(&pair<const int, int>::first, *begin(arg1))

LWS demo


作为最后一点,我将添加指定C ++ 11绑定表达式,使得指向成员的指针可以在使用operator*任何上工作。所以你可以开箱即用:

bind(&pair<const int, int>::first, bind(static_cast<begin_type>(&std::map<int, int>::begin), _1))

LWS demo