0

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

  • 收到地图 m
  • 返回 m.begin()->first

为此,我正在尝试使用 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));

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

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

但这行不通,因为没有全局运算符*。

问题:

  • 是否可以使用 boost::bind 复合链来实现这一点?如何?
  • 更容易阅读的替代方案?
4

2 回答 2

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;
};
于 2013-04-10T17:28:16.673 回答
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 演示

但凤凰的另一个优点是它带有一些电池。在我们的案例中,我们非常感兴趣,<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 演示


作为最后一点,我将补充一点,C++11 绑定表达式是指定的,因此指向成员的指针适用于任何使用operator*. 所以开箱即用,您可以执行以下操作:

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

LWS 演示

于 2013-04-10T17:30:51.593 回答