2013-10-23 22 views
2

我希望能够从两个分配给参考值的boost::fusion::map分配到地图引用:从地图中的值/引用一个

  • 值的boost::fusion::map
  • boost::fusion::map的参考文献。

什么是正确的(通用和惯用的)方式来做到这一点?

// Let: 
using bf = boost::fusion; 
struct A {}; struct B{}; 

// I have a map of references 
using my_ref_map = bf::map<bf::pair<A, float&>, bf::pair<B, int&>>; 

// and a map of values: 
using my_val_map = bf::map<bf::pair<A, float>, bf::pair<B, int>>; 

// Say I have two values and I make a map of references 
float a; int b; 
my_ref_map MyRefMap(bf::make_pair<A>(a), bf::make_pair<B>(b)); 

// Then I wanto to set a and b using both: 
// a map of values: 
my_val_map MyValMap(bf::make_pair<A>(2.0), bf::make_pair<B>(3)) 

// and a map of references: 
float aSrc = 2.0; int bSrc = 3; 
my_ref_map MyRefMap(bf::make_pair<A>(aSrc), bf::make_pair<B>(bSrc)); 

// ... some code ... (see below for the things I've tried) 

assert(a == 2.0 && b == 3); // <- End result. 

我已经试过如下:

bf::copy(MyValMap, MyRefMap); 
// copy complains that bf::pair<A, float&> cannot be assigned 
// because its copy assignment operator is implicitly deleted. 
// This is fine, I wasn't expecting copy to work here. 

实现一个bf::zip_non_const(见下文),它允许你修改地图,做:

bf::for_each(bf::zip_non_const(MyRefMap, MyValMap), [](auto i) { 
    bf::at_c<0>(i) = bf::at_c<1>(i); }); 
// This works but bf::zip returns const& for a reason: 
// there has to be a better way. 

这是我执行zip_non_const

namespace boost { namespace fusion { 
// Boilerplate: 
namespace result_of { 
template<class... Ts> struct zip_non_const { 
    using sequences = mpl::vector<Ts...>; 
    using ref_params 
    = typename mpl::transform<sequences, add_reference<mpl::_> >::type; 
    using type = zip_view<typename result_of::as_vector<ref_params>::type>; 
}; 
} 

// zip_non_const 
template<class... Ts> 
inline typename result_of::zip_non_const<Ts...>::type zip_non_const(Ts&&... ts) 
{ return {fusion::vector<Ts&&...>(ts...)}; } 

// swap for fusion types 
template <class T> inline void swap(T&& lhs, T&& rhs) noexcept { 
    using std::swap; 
    std::remove_reference_t<T> tmp = lhs; 
    lhs = rhs; 
    rhs = tmp; 
} 

} // namespace fusion 
} // namespace boost 
+0

将[这里](http://coliru.stacked-crooked.com/a/e04527bcc04c7d0d)工作? (如果你满意,我会把它作为答案)。 – llonesmiz

+0

是的,它的工作原理!所以你迭代for_each中的输入(应该由const&anyway来处理)并修改lambda中的“输出”?我认为不能修改const成员函数中的成员非const引用,但似乎并非如此。真的很酷,谢谢!把它作为答案,我会接受它。 – gnzlbg

回答

1

fusion::map定义了一个允许赋值的=运算符。在将my_val_map分配给my_ref_map时,此功能正常工作,但在分配介于两个my_ref_map之间时遇到与fusion::copy相同的错误时失败。在下面的代码中,我只是遍历第一个地图中的对,然后将数据分配给目标地图中的相应对。
重要的是,目标地图具有所有正在复制的地图中存在的关键点,否则您将收到编译错误。 (如果您有Map1=map<pair<A,int> >; Map2=map<pair<A,int>, pair<B,float> >;,则可以从Map1复制到Map2,但不能从Map2复制到Map1)。
Live Example

#include <iostream> 

#include <boost/fusion/include/map.hpp> 
#include <boost/fusion/include/for_each.hpp> 
#include <boost/fusion/include/at_key.hpp> 

namespace fusion = boost::fusion; 
struct A {}; struct B{}; 

// I have a map of references 
using my_ref_map = fusion::map<fusion::pair<A, float&>, fusion::pair<B, int&>>; 

// and a map of values: 
using my_val_map = fusion::map<fusion::pair<A, float>, fusion::pair<B, int>>; 

template<typename MapOut> 
struct map_assigner //you could use a c++14 lambda if your compiler supports it 
{ 
    map_assigner(MapOut& map):map_out(map){} 

    template <typename Pair> 
    void operator()(const Pair& pair) const 
    { 
     fusion::at_key<typename Pair::first_type>(map_out) = pair.second; 
    } 

    MapOut& map_out; 
}; 

template <typename MapIn, typename MapOut> 
void my_copy(const MapIn& map_in, MapOut& map_out) 
{ 
    fusion::for_each(map_in,map_assigner<MapOut>(map_out)); 
} 


int main() 
{ 

    // Say I have two values and I make a map of references 
    float a=0.0f; 
    int b=0; 
    my_ref_map MyRefMap(fusion::make_pair<A,float&>(a), fusion::make_pair<B,int&>(b)); 

    // Then I wanto to set a and b using both: 
    // a map of values: 
    my_val_map MyValMap(fusion::make_pair<A>(2.0f), fusion::make_pair<B>(3)); 

    // and a map of references: 
    float aSrc = 4.0f; int bSrc = 6; 
    my_ref_map MyRefMap2(fusion::make_pair<A,float&>(aSrc), fusion::make_pair<B,int&>(bSrc)); 

    my_copy(MyValMap,MyRefMap); 

    std::cout << "a=" << a << ", b=" << b << std::endl; // <- End result. 

    my_copy(MyRefMap2,MyRefMap); 

    std::cout << "a=" << a << ", b=" << b << std::endl; // <- End result. 
} 
+0

你已经拿起一个不错的爱好:) – gnzlbg

相关问题