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));
}