The canonical way to update / replace the map value in `boost :: hana :: map`

What is the canonical way to update a value (given the key and the new value) inside boost::hana::map ?

I tried using boost::hana::replace_if , but it doesn’t work on map , since it is not Functor - I can get it to work by converting map to tuple and then back to map , but it sounds inefficient.

The alternative I'm using right now is calling map::erase_key , followed by map::insert .

Is there any replace or update function designed for this purpose that might be missing? Or is it a “canonical” way of updating a value?

+5
source share
2 answers

I do not think there is currently a canonical way to do this. If there are valid use cases for this, perhaps we could get a function there to support it. The problem with hana::erase_key is that you create a new map and then again using hana::insert . Currently using hana::unpack and then creating a new map is probably best.

 #include <boost/hana.hpp> namespace hana = boost::hana; template <typename NewPair> struct replace_helper_t { NewPair const& new_pair; template <typename Pair> constexpr decltype(auto) operator()(Pair&& p) const { return hana::if_( hana::equal(hana::first(new_pair), hana::first(p)), new_pair, std::forward<Pair>(p) ); } }; struct replace_t { template <typename Map, typename NewPair> constexpr auto operator()(Map&& m, NewPair&& new_pair) const { return hana::unpack(std::forward<Map>(m), hana::on( hana::make_map, replace_helper_t<NewPair>{std::forward<NewPair>(new_pair)} ) ); } }; constexpr replace_t replace{}; int main() { auto my_map = hana::make_map( hana::make_pair(hana::int_c<7>, 7), hana::make_pair(hana::int_c<13>, 13), hana::make_pair(hana::int_c<23>, 23) ); auto new_map = replace(my_map, hana::make_pair(hana::int_c<13>, 14.0f)); BOOST_HANA_RUNTIME_ASSERT(new_map == hana::make_map( hana::make_pair(hana::int_c<7>, 7), hana::make_pair(hana::int_c<13>, 14.0f), hana::make_pair(hana::int_c<23>, 23) ) ); } 

In another note, perhaps hana::map should be Functor .

+4
source

Do you need to change the type of value? If not, and if your value can be assigned, you can use map[key] = new_value or equivalently hana::at_key(map, key) = new_value , since hana::at_key returns a link.

If you need to change the type of value, this is more complicated. We will not be able to do anything in place, because the type of card after replacing the value will be different from its type before replacing the value. Therefore, we must create a new map or some modified representation of this map (but representations are not currently supported). Using erase_key and insert will actually create two cards, which is inefficient. Instead, we could provide some update function that would achieve the same, but create only one copy of the map (result). I believe that we could do better than erase_key + insert in terms of compilation time by providing our own function. I discovered this problem in order to track your request, since I think it is important to provide something like this; thanks.

Finally, I would like to comment on what Jason said:

In another note, perhaps hana :: map should be Functor.

hana::map could be made Functor, but I'm not sure that transform can touch the map keys, while observing the laws of Functor. If this is not the case, you still cannot say "replace the value with XXX if the key satisfies some predicates" using, for example, hana::replace_if . I tried (but failed so far) to find an example of functions that would violate laws if hana::transform basically transformed the sequence of underlying key / value pairs, but my intuition is that you can find such an example. To be continued in issue No. 278.

+2
source

All Articles