4

現在、boost::fusion::for_each は単一のシーケンスの要素を繰り返します。同様の方法で機能する関数を作成しようとしていますが、多くのシーケンスがあり、シーケンス間のすべての可能な組み合わせを反復処理します。

たとえば、S1、S2、S3 の 3 つのシーケンスがある場合、このようなファンクターを作成したいと思います

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, s2, s3

ここで、s1、s2、s3 は S1、S2、S3 のインスタンスです。

一般的なケース (任意の数のシーケンス) のコードを書くことから始めましたが、難しすぎることがわかりました。そこで、2 つのシーケンスだけから始めて、そこから取得することにしました。次のような 2 つのシーケンス (簡単にするために 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 Seq2, int i1, class F>                                         
struct my_call<Seq1, Seq2, i1, boost::mpl::size<Seq2>::type::value - 1, F> {                               

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

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

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


// the actual function                                                         
template <class Seq1, class Seq2, class F>                                             
void for_each(Seq1& seq1, Seq2& seq2, F& f) {                                              
  my_call<Seq1, Seq2, 0, 0, F>::apply(seq1, seq2, 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;
}

私の主な (しゃれは意図されていません) 問題は、任意の数のシーケンスで動作するように上記を一般化することです。どんな提案でも大歓迎です!ありがとう

4

1 に答える 1