I have two boost::fusion::map
s that I want to merge in a certain way. For the two maps I want to generate a third that has all the keys present in both maps and the values are added if both a present. For example:
#include <boost/fusion/container/map.hpp>
namespace bfn = boost::fusion;
using namespace boost::fusion;
struct x{};
struct y{};
struct z{};
int main(){
auto m = make_map<x, y>(2, 4.3);
auto n = make_map<x>(2.);
auto l = accumulate_merge(m, n); // how this function should look like?
}
After that l
will be equivalent to make_map<x, y>(2 + 2., 4.3)
.
I have no clue where to start. I tried to begin with join
(and the eliminate duplicates but I got complicated pretty fast).
Is there a tool in Boost Fusion that can help me?
(There are lots of subtleties like what to do if for the same key the two corresponding types are different --but still addable--. But any first version will help).
I managed to come up with this version using
boost::fusion::fold
twice. I am not sure if it is (compile-time) optimal.Basically, I iterate first over the first map. If the key is not in the second map the element is pushed to the result. If the key is in the second map the elements are added and the result (whatever the type is pushed to the result).
Finally, I iterate in the second map. If the key is in the first map I ignore it (because it was added in the first pass). If the key is not in the second the element is pushed to the result.
(The result is that the first map has precedence for the ordering of the key types)
There are some open issues or doubts:
1) there is a more efficient/compact way of doing this
2) I wasn't sure about the use of
forward
basically I used it everywhere (just in case)3) not sure about the
auto
vs.decltype(auto)
in the function returns.4) The functions are not SFINAE friendly, I could add guards to generate soft errors. (For example if values cannot be added).
5) The result doesn't have any natural order, I don't know if this is a problem with the algorithm or with fold or because map don't specify an order with
push_back
(after all it is a map).Now the code: