加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C:boost :: fusion :: for_each用于许多序列

发布时间:2020-12-16 07:09:09 所属栏目:百科 来源:网络整理
导读:目前,boost :: fusion :: for_each迭代单个序列的元素.我正在尝试创建一个函数,它将以类似的方式工作,但具有许多序列,并将迭代序列之间的所有可能组合. 例如,如果我有三个序列S1,S2,S3,我想创建一个像这样的仿函数 struct my_functor {template class x,clas
目前,boost :: fusion :: for_each迭代单个序列的元素.我正在尝试创建一个函数,它将以类似的方式工作,但具有许多序列,并将迭代序列之间的所有可能组合.

例如,如果我有三个序列S1,S2,S3,我想创建一个像这样的仿函数

struct my_functor {

template <class x,class y,class z>
void operator()(x& el1,y& el2,z& el3) {...}
}

然后打电话

for_each(s1,s2,s3,my_functor()) // applies the functor to all combinations of elements of s1,s3

其中s1,s3是S1,S3的实例.

我开始编写一般情况的代码(任意数量的序列),但发现它太难了.所以我决定从两个序列开始并从那里开始.当我有两个序列(为简单起见假设fusion :: vectors)时,我已设法完成它,如下所示:

//for_each.hpp

#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/back.hpp>
#include <boost/mpl/size.hpp>

template <class Seq1,class Seq2,int i1,int i2,class F>                                     
struct my_call {                                                           

  static void apply(Seq1& seq1,Seq2& seq2,F& f) {                                        
    f(boost::fusion::at_c<i1>(seq1),boost::fusion::at_c<i2>(seq2)); // apply functor for a given pair of ints             
    my_call<Seq1,Seq2,i1,i2+1,F>::apply(seq1,seq2,f); // increase second int by 1 and apply functor again            
  }                                                                
};                                                                 

// terminal condition for 2nd sequence                                                 
template <class Seq1,class F>                                         
struct my_call<Seq1,boost::mpl::size<Seq2>::type::value - 1,F> {                               

  static void apply(Seq1& seq1,boost::fusion::back(seq2));                                   
    my_call<Seq1,i1+1,f); // reset 2nd int and increase 1st by 1                  
  }                                                                
};                                                                 

// terminal condition for both sequences                                               
template <class Seq1,class F>                                             
struct my_call<Seq1,F> {          

  static void apply(Seq1& seq1,F& f) {                                        
    f(boost::fusion::back(seq1),boost::fusion::back(seq2));                                       
  }                                                                
};                                                                 


// the actual function                                                         
template <class Seq1,class F>                                             
void for_each(Seq1& seq1,F& f) {                                              
  my_call<Seq1,f);                                          
}

和主要的

//main.cpp
#include "for_each.hpp"
#include <iostream>

struct myf {
  template <class X,class Y>
  void operator()(X& x,Y& y) {
    std::cout << x + y << std::endl;
  }
};

int main() {
  boost::fusion::vector<int,double> x(1,2.5);
  boost::fusion::vector<double,int> y(2,5);
  myf F;
  for_each(x,y,F);
  return 0;
}

我的主要(没有双关语)问题是推广上述内容以使其适用于任意数量的序列.任何建议都非常欢迎!谢谢

解决方法

您可以创建序列序列并将它们传递给调用函数.

int main()
{
    boost::fusion::vector<int,2.5);
    boost::fusion::vector<double,5);
    boost::fusion::vector<double,double,double> z(10,20,30);

    CallFunc(myf(),boost::fusion::make_vector(x,y));
    CallFunc(myf(),z));
}

CallFunc从每个序列的元素生成笛卡尔积,然后将它们传递给给定的仿函数.

#include <iostream>

#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/container/generation/make_vector.hpp>
#include <boost/fusion/algorithm/iteration/for_each.hpp>
#include <boost/fusion/include/empty.hpp>
#include <boost/fusion/include/pop_front.hpp>
#include <boost/fusion/include/front.hpp>
#include <boost/fusion/include/push_back.hpp>
#include <boost/fusion/include/invoke.hpp>

struct myf {
    typedef void result_type;

    template <class X,class Y>
    void operator()(X x,Y y) {
        std::cout << x + y << std::endl;
    }
    template <class X,class Y,class Z>
    void operator()(X x,Y y,Z z) {
        std::cout << x + y + z << std::endl;
    }
};

template<class Stop> struct CallFuncOuter;

template<class Func,class Tail,class CallTuple>
struct CallFuncInner
{
    CallFuncInner(Func &f,Tail &seq,CallTuple & args)
        : f(f),tail(seq),args(args)
    {
    }

    template<class HeadArg>
    void operator()(HeadArg & head_arg) const
    {
        CallFuncOuter<boost::fusion::result_of::empty<Tail>::type>()
            (f,tail,boost::fusion::push_back(args,head_arg));
    }

    Func &f;
    Tail &tail;
    CallTuple &args;
};

template<class Func,class CallTuple>
CallFuncInner<Func,Tail,CallTuple> MakeCallFuncInner(Func &f,Tail &tail,CallTuple &arg)
{
    return CallFuncInner<Func,CallTuple>(f,arg);
}

template<class Stop>
struct CallFuncOuter
{
    template<class Func,class SeqOfSeq,class CallTuple>
    void operator()(Func &f,SeqOfSeq & seq,CallTuple & args) const
    {
        boost::fusion::for_each(boost::fusion::front(seq),MakeCallFuncInner(
                f,boost::fusion::pop_front(seq),args));
    }
};

template<>
struct CallFuncOuter<boost::mpl::true_>
{
    template<class Func,CallTuple & args) const
    {
        boost::fusion::invoke(f,args);
    }
};

template<class Func,class SeqOfSeq>
void CallFunc(Func &f,SeqOfSeq & seq)
{
    CallFuncOuter<boost::fusion::result_of::empty<SeqOfSeq>::type>()
        (f,seq,boost::fusion::vector<>());
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读