C++11 基于关键点合并两个Boost融合贴图

C++11 基于关键点合并两个Boost融合贴图,c++11,merge,boost-fusion,C++11,Merge,Boost Fusion,我有两个boost::fusion::maps要以某种方式合并。对于这两个贴图,我想生成第三个,它在两个贴图中都有所有的键,如果两个贴图都存在,则添加值。例如: #include <boost/fusion/container/map.hpp> namespace bfn = boost::fusion; using namespace boost::fusion; struct x{}; struct y{}; struct z{}; int main(){ auto

我有两个
boost::fusion::map
s要以某种方式合并。对于这两个贴图,我想生成第三个,它在两个贴图中都有所有的键,如果两个贴图都存在,则添加值。例如:

#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?
}
#包括
名称空间bfn=boost::fusion;
使用名称空间boost::fusion;
结构x{};
结构y{};
结构z{};
int main(){
自动m=制作地图(2,4.3);
自动n=制作地图(2);
auto l=accumulate\u merge(m,n);//这个函数应该是什么样子?
}
之后,
l
将等同于
make_map(2+2,4.3)

我不知道从哪里开始。我试着从
join
开始(并消除重复项,但我很快就变得复杂起来)

在Boost Fusion中有什么工具可以帮助我吗


(有很多微妙之处,比如如果同一个键的两个对应类型不同,但仍然可以添加,但任何第一个版本都会有所帮助)。

我两次使用了
boost::fusion::fold来设计这个版本。我不确定它(编译时)是否最优

基本上,我首先迭代第一个映射。如果键不在第二个贴图中,则将元素推送到结果。如果键位于第二个映射中,则添加元素并返回结果(无论将何种类型推送到结果)

最后,我在第二个映射中迭代。如果关键点在第一个贴图中,我将忽略它(因为它是在第一个过程中添加的)。如果键不在第二个位置,则将元素推送到结果

(结果是第一个映射具有键类型排序的优先级)

有一些悬而未决的问题或疑问:

1) 有一种更高效/紧凑的方法来实现这一点

2) 我不确定如何使用
forward
基本上我在任何地方都使用它(以防万一)

3) 不确定函数返回中的
auto
decltype(auto)
的对比

4) 这些函数对SFINAE不友好,我可以添加防护来生成软错误。(例如,如果无法添加值)

5) 结果没有任何自然顺序,我不知道这是否是算法或折叠的问题,或者因为map没有使用
push_back
指定顺序(毕竟它是一个map)

欢迎评论

现在代码是:

namespace boost{
namespace fusion{
namespace detail{
template<class Map2>
struct merge1{
    Map2 m2_;
    template<typename MapOut, typename Pair1>
    auto operator()(MapOut&& mo, Pair1&& p1) const{
        return conditional_push_back(std::forward<MapOut>(mo), std::forward<Pair1>(p1), has_key<typename std::decay_t<Pair1>::first_type>(m2_));
    }
    template<typename MapOut, typename Pair1> 
    auto conditional_push_back(MapOut&& mo, Pair1&& p1, mpl_::bool_<false>) const{
        return push_back(std::forward<MapOut>(mo), std::forward<Pair1>(p1));
    }
    template<typename MapOut, typename Pair1>
    auto conditional_push_back(MapOut&& mo, Pair1&& p1, mpl_::bool_<true>) const{
        return push_back(std::forward<MapOut>(mo), make_pair<typename std::decay_t<Pair1>::first_type>(p1.second + at_key<typename std::decay_t<Pair1>::first_type>(m2_)));
    }
};
template<class Map2>
merge1<Map2> make_merge1(Map2&& m2){return {std::forward<Map2>(m2)};}

template<class Map1>
struct merge2{
    Map1 m1_;
    template<typename MapOut, typename Pair2>
    auto operator()(MapOut&& mo, Pair2&& p2) const{
        return conditional_push_back(std::forward<MapOut>(mo), std::forward<Pair2>(p2), has_key<typename std::decay_t<Pair2>::first_type>(m1_));
    }
    template<typename MapOut, typename Pair2>
    auto conditional_push_back(MapOut&& mo, Pair2&& p2, mpl_::bool_<false>) const{
        return push_back(std::forward<MapOut>(mo), std::forward<Pair2>(p2));
    }
    template<typename MapOut, typename Pair2>
    auto conditional_push_back(MapOut&& mo, Pair2&&   , mpl_::bool_<true>) const{
        return mo;
    }
};
template<class Map1> 
merge2<Map1> make_merge2(Map1&& m){return {std::forward<Map1>(m)};}
}

template<class Map1, class Map2>
inline auto accumulate_merge(Map1&& m1, Map2&& m2){
    return 
        as_map( // not completely sure this is a good idea
            fold( // second map2 is checked for unpaired elements
                std::forward<Map1>(m1), 
                fold( // first map1 takes the lead
                    std::forward<Map2>(m2), 
                    make_map<>(), 
                    detail::make_merge1(std::forward<Map1>(m1))
                ), 
                detail::make_merge2(std::forward<Map2>(m2))
            )
        );
}
}}

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<   y, z>(   2  , 8.);
    auto l = accumulate_merge(m, n);
    assert( at_key<x>(l) == at_key<x>(m) );
    assert( at_key<y>(l) == at_key<y>(m) + at_key<y>(n) );
    assert( typeid(at_key<y>(l)) == typeid(at_key<y>(m) + at_key<y>(n)) );
    assert( at_key<z>(l) == at_key<z>(n) );
}
namespace boost{
名称空间融合{
名称空间详细信息{
模板
结构合并1{
MAP2m2;
模板
自动运算符(){
返回条件推送(std::forward(mo)、std::forward(p1)、has_键(m2_));
}
模板
自动条件推送(映射输出和mo、Pair1和p1、mpl::bool)常量{
返回推回(std::forward(mo),std::forward(p1));
}
模板
自动条件推送(映射输出和mo、Pair1和p1、mpl::bool)常量{
返回push_back(标准::forward(mo),生成_对(p1.second+at_键(m2_));
}
};
模板
merge1 make_merge1(Map2&&m2){return{std::forward(m2)};}
模板
结构合并2{
map1m1;
模板
自动运算符(){
返回条件推送(std::forward(mo)、std::forward(p2)、has_键(m1_));
}
模板
自动条件推送(映射输出和mo、Pair2和p2、mpl::布尔)常量{
返回push_-back(标准:向前(mo),标准:向前(p2));
}
模板
自动条件推送(映射输出和mo、Pair2和mpl::布尔)常量{
返回任务单;
}
};
模板
merge2 make_merge2(Map1&&m){return{std::forward(m)};}
}
模板
内联自动累积合并(Map1和m1、Map2和m2){
返回
如图所示(//不完全确定这是个好主意
fold(//检查第二个map2是否有未配对的元素
标准::正向(m1),
fold(//第一个map1领先
标准:正向(m2),
make_map(),
细节:使合并1(标准:向前(m1))
), 
详图:合并2(标准:向前(m2))
)
);
}
}}
名称空间bfn=boost::fusion;
使用名称空间boost::fusion;
结构x{};
结构y{};
结构z{};
int main(){
自动m=制作地图(2,4.3);
自动n=制作地图(2,8.);
自动l=累积和合并(m,n);
断言(在键(l)=在键(m));
断言(at_键(l)=at_键(m)+at_键(n));
断言(typeid(at_键(l))==typeid(at_键(m)+at_键(n));
断言(在键(l)=在键(n));
}