Search code examples
c++boost-hana

Boost hana fold_left lambda call by reference


I want to traverse through a multimap (map of maps) e.g.: map<int,map<char, string>> with the help of boost hana. The lambda function at can't take a reference type &map (compile error: non-const reference), thus, I can't load or store elements in the multimap.

   template <typename T_Map, typename T_Tuple>
   auto& traverse(T_Map &map, T_Tuple &keys){
      auto at = [](auto &map, auto key) -> auto& {
          return map[key];
      };     
      return hana::fold_left(keys, map, at);
   }

Is it possible to solve this problem with boost::hana like I did ? Or is there some other way ?

Update 1:

Previous Solution without hana need parameter packs. But I need a function that accepts keys as tuple.

template <typename T_Map, typename T, typename... Ts>
auto& traverse(T_Map &map, T key, Ts... keys){
    return traverse(map[key], keys...);
}

template <typename T_Map, typename T>
auto& traverse(T_Map& map, T key){
    return map[key];

}

Solution

  • I fixed two bugs that prevented your use case from working properly. Here's a minimal complete example that currently works on master:

    #include <boost/hana/at_key.hpp>
    #include <boost/hana/fold_left.hpp>
    #include <boost/hana/integral_constant.hpp>
    #include <boost/hana/map.hpp>
    #include <boost/hana/pair.hpp>
    #include <boost/hana/range.hpp>
    
    #include <cassert>
    namespace hana = boost::hana;
    
    
    auto at = [](auto& map, auto key) -> auto& {
        return map[key];
    };
    
    template <typename Map, typename Keys>
    auto& traverse(Map& map, Keys const& keys){
        return hana::fold_left(keys, map, at);
    }
    
    int main() {
        auto xs = hana::make_map(hana::make_pair(hana::int_c<0>,
                    hana::make_map(hana::make_pair(hana::int_c<1>,
                        hana::make_map(hana::make_pair(hana::int_c<2>,
                            hana::make_map(hana::make_pair(hana::int_c<3>, 10))))))));
    
        int& i = traverse(xs, hana::range_c<int, 0, 4>);
        assert(i == 10);
        i = 99;
        assert(traverse(xs, hana::range_c<int, 0, 4>) == 99);
    }