Boost.Bind to access std::map elements in std::for_each

后端 未结 4 836
后悔当初
后悔当初 2020-12-16 03:49

I\'ve got a map that stores a simple struct with a key. The struct has two member functions, one is const the other not. I\'ve managed calling the const function using std::

相关标签:
4条回答
  • 2020-12-16 04:30

    If you find yourself having to do this a lot I recommend you use the Boost.RangeEx library:

    #include <boost/range/algorithm/for_each.hpp>
    #include <boost/range/adaptor/map.hpp>
    #include <boost/mem_fn.hpp>
    #include <map>
    
    struct MyStruct {
      void someConstFunction() const;
      void someFunction();
    };
    
    typedef std::map<int, MyStruct> MyMap;
    MyMap theMap;
    
    int main()
    {
        //call the const member function
        boost::for_each(theMap | boost::adaptors::map_values,
                        boost::mem_fn(&MyStruct::someConstFunction));
    
        //call the non-const member function
        boost::for_each(theMap | boost::adaptors::map_values,
                        boost::mem_fn(&MyStruct::someFunction));
    }
    

    It's been accepted into Boost but it doesn't come with the official distribution yet. Until it does you can download it from the Boost Vault (download link to zip file).

    0 讨论(0)
  • 2020-12-16 04:33

    One problem I spotted: the second bind is called for a non function member. second is a data member, not a method of std::pair

    0 讨论(0)
  • 2020-12-16 04:36

    IIRC, Boost.Bind uses boost::mem_fn for its binding to members capability. Now, if you look at mem_fun (scroll down to the // data member support part), you'll see that it typedefs its result_type as a const&, while is still has overloads of the function call operator supporting the extraction of a non-const member from a non-const argument.

    It thus seems that the problem is that this confuses Boost.Bind's return type deduction mechanism. A solution would thus to explicitly tell Bind that the result is not const:

    //call the non-const member function
    std::for_each(theMap.begin(), theMap.end(),
       boost::bind(&MyStruct::someFunction, 
           boost::bind<MyStruct&>(&MyMap::value_type::second, _1)
       )
    );
    
    0 讨论(0)
  • 2020-12-16 04:48

    If you are already depend on Boost, you may be willing to check Boost Foreach

    BOOST_FOREACH(MyMap::value_type const& val, MyMap)
    {
      val.second.someConstFunction();
    }
    

    Much much readable, though I don't know about performance issues.

    Also note that you can't use templated typed within the macro without "escaping" the , character:

    • either by a typedef before
    • or by using a second pair of parenthesis around the type
    0 讨论(0)
提交回复
热议问题