Search code examples
c++boostc++11dictionaryboost-range

How to declare boost range adaptor (e.g. map_values)


Say I have

class Value;
class Key;

class MyClass {
  private:
  std::map<Key,Value> my_map;
  ....
}

Inside of MyClass methods I have a very convenient way to iterate through values of my_map by saying

 for( auto& value: my_map | boost::adaptors::map_values) {
    ...
 }

However I would like to have a method of MyClass that would essentially output my_map | boost::adaptors::map_values and allow convenient value iteration outside of MyClass methods. How do I declare such a method? Would I need to implement some sort of pseudo container and corresponding iterator or there is a shortcut?


Solution

  • Basically, you have two good choices. You can provide users with a nicely decoupled interface by using boost's any_range, or else if you need the best performance, you can give clients direct access to the adapted range using c++11 decltypes. In the first case, clients won't have to change if you change implementation, but this comes at a cost of extra redirection.

    using any_range:

    #include <boost/range.hpp> 
    #include <map> 
    #include <boost/range/adaptor/map.hpp> 
    #include <boost/range/any_range.hpp>
    
    class Foo 
    { 
        std::map<int, int> my_map;
        boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> Values()
        { return my_map | boost::adaptors::map_values; }
    }; 
    

    giving direct access (awkward syntax here is because you require VS2013, which doesn't support member variables in unevaluated context at class scope):

    #include <boost/range.hpp> 
    #include <map> 
    #include <boost/range/adaptor/map.hpp> 
    
    class Foo 
    { 
        std::map<int, int> my_map;
        auto Values() -> decltype(my_map | boost::adaptors::map_values)
        { return my_map | boost::adaptors::map_values; }
    };