2017-01-01 171 views
2

将std :: vector初始状态应用boost :: fusion :: fold可以正常工作。使用fusion :: vector初始化状态折叠

#include <vector> 
#include <boost/fusion/container/map.hpp> 
#include <boost/fusion/container/vector.hpp> 
#include <boost/fusion/include/fold.hpp> 
struct A; 
struct B; 
struct C; 
int ia = 1, ib = 2, ic = 3; 
namespace fusion = boost::fusion; 

template< typename StdInteratorT> 
struct initialize_map_with_std_vector 
{ 
    template<class T> 
    StdInteratorT operator()(StdInteratorT& i, T& val) { 
     val = *i; 
     return ++i; 
    } 
}; 

void use_fold_with_std_vector() 
{ 
    using M = fusion::map<fusion::pair<A, int>, fusion::pair<B, char>, fusion::pair<C, double>>; 
    M fm; 
    std::vector<int> sv = { ia, ib, ic }; 
    auto state = sv.begin(); 
    fusion::fold(fm, state, initialize_map_with_std_vector<std::vector<int>::iterator>()); 
} 

int main() { use_fold_with_std_vector(); } 

当同样的概念应用到融合::但是向量,代码失败,出现错误编译 no instance of overloaded function "boost::fusion::fold" matches the argument

#include <vector> 
    #include <boost/fusion/container/map.hpp> 
    #include <boost/fusion/container/vector.hpp> 
    #include <boost/fusion/include/fold.hpp> 
    #include <boost/fusion/algorithm/iteration/fold.hpp> 
    namespace fusion = boost::fusion; 

    struct A; 
    struct B; 
    struct C; 
    std::vector<int> va = { 4, 5, 6 }; 
    std::vector<char> vb = { 'a', 'b', 'c' }; 
    std::vector<double> vc = { 10., 11., 12. };  

    template< typename FusionIteratorT, typename Ret> 
    struct initialize_map_with_fusion_vector { 

     template<typename T> 
     Ret operator()(FusionIteratorT& i, T& val) { 
      val = fusion::deref(i); 
      return fusion::next(i); 
     } 
    }; 

    void use_fold_with_fusion_vector() { 
     using M = fusion::map<fusion::pair<A, std::vector<int>>, fusion::pair<B, std::vector<char>>, fusion::pair<C, std::vector<double>>>; 
     using V = fusion::vector<std::vector<int>, std::vector<char>, std::vector<double>>; 
     auto fm = M(); 
     auto fv = V(va, vb, vc); 
     using FusionIteratorT = decltype(fusion::begin(fv)); 
     using Ret = fusion::result_of::next<fusion::result_of::begin<decltype(fv)>>; 
     fusion::fold(fm, fusion::begin(fv), 
      initialize_map_with_fusion_vector<FusionIteratorT, Ret >()); 
} 

int main() {use_fold_with_fusion_vector();} 

如何让融合::倍工作与融合::矢量初始值设定项?

+0

你的第一个示例代码不编译http://coliru.stacked-crooked.com/a/eb2d41fef08642ab –

+0

道歉。复制粘贴错误我已更正此错误。 – hhbilly

+0

http://coliru.stacked-crooked.com/a/490dd711ec829912 – hhbilly

回答

0

有一点需要注意,使用Boost.Hana是因为hana::Foldable需要在编译时知道容器的长度,所以std::vector在没有运行时检查的情况下不能正常工作。

考虑这个例子:

#include <boost/hana.hpp> 
#include <iostream> 
#include <stdexcept> 
#include <vector> 

namespace hana = boost::hana; 

struct A { }; 
struct B { }; 
struct C { }; 

constexpr auto keys = hana::make_tuple(
    hana::type_c<A>, 
    hana::type_c<B>, 
    hana::type_c<C> 
); 

template <typename Keys, typename T> 
auto make_map_from_vector(Keys keys, std::vector<T> const& v) 
{ 
    // Run-time check of vector length 
    if (v.size() != hana::length(keys)) 
    throw std::runtime_error(
     "I should've used std::array instead of std::vector! " 
     "The length of std::array is known at compile-time." 
    ); 

    return hana::unpack(
    hana::make_range(hana::size_c<0>, hana::length(keys)), 
    [&](auto ...i) 
    { 
     return hana::make_map(
     hana::make_pair(hana::at(keys, i), v[i])... 
    ); 
    } 
); 
} 

int main() 
{ 
    auto my_map = make_map_from_vector(keys, std::vector<char>{'a', 'b', 'c'}); 
    std::cout << "A => " << my_map[hana::type_c<A>] << '\n'; 
    std::cout << "B => " << my_map[hana::type_c<B>] << '\n'; 
    std::cout << "C => " << my_map[hana::type_c<C>] << '\n'; 

    // explosions 
    make_map_from_vector(keys, std::vector<char>{'a', 'b'}); 
} 

输出:

A => a 
B => b 
C => c 
terminate called after throwing an instance of 'std::runtime_error' 
    what(): I should've used std::array instead of std::vector! The length of std::array is known at compile-time. 
Aborted (core dumped) 
+1

看起来像Hana的正确答案。还要注意,你可以使用'hana :: tuple'而不是'std :: vector',它应该可以正常工作(用'hana :: size(v)'替换'v.size它回答了原来的问题。 –