代码之家  ›  专栏  ›  技术社区  ›  ricab

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

  •  0
  • ricab  · 技术社区  · 12 年前

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

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

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

    但由于没有全球运营商,这是行不通的。

    问题:

    • 是否可以使用boost::绑定复合链来实现这一点?怎样
    • 更容易阅读的替代方案?
    2 回复  |  直到 12 年前
        1
  •  1
  •   Luc Danton    12 年前

    我强烈推荐 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 )

    但Phoenix的另一个优点是它配备了一些电池。就我们而言,我们非常感兴趣 <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 )

        2
  •  1
  •   Arne Mertz    12 年前

    您可以使用成员函数指针调用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;
    };