gpt4 book ai didi

C++: boost::fusion::for_each 对于许多序列

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:17:27 27 4
gpt4 key购买 nike

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

其中 s1、s2、s3 是 S1、S2、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 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;
}

我的主要(没有双关语意)问题是对上述内容进行概括,使其适用于任意数量的序列。非常欢迎任何建议!谢谢

最佳答案

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

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

CallFunc(myf(), boost::fusion::make_vector(x, y));
CallFunc(myf(), boost::fusion::make_vector(x, y, 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 Tail, class CallTuple>
CallFuncInner<Func, Tail, CallTuple> MakeCallFuncInner(Func &f, Tail &tail, CallTuple &arg)
{
return CallFuncInner<Func, Tail, CallTuple>(f, tail, 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, class SeqOfSeq, class CallTuple>
void operator()(Func &f, SeqOfSeq & seq, 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<>());
}

关于C++: boost::fusion::for_each 对于许多序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24441236/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com