gpt4 book ai didi

C++ 迭代器流水线设计

转载 作者:IT老高 更新时间:2023-10-28 23:01:47 29 4
gpt4 key购买 nike

假设我们要应用一系列变换,int f1(int)int f2(int)int f3(int),到对象列表。一种天真的方法是

SourceContainer source;

TempContainer1 temp1;
transform(source.begin(), source.end(), back_inserter(temp1), f1);
TempContainer2 temp2;
transform(temp1.begin(), temp1.end(), back_inserter(temp2), f2);

TargetContainer target;
transform(temp2.begin(), temp2.end(), back_inserter(target), f3);

由于 temp1temp2 需要额外的空间,这个 first 解决方案并不是最佳的。所以,让我们变得更聪明:

int f123(int n) { return f3(f2(f1(n))); }
...
SourceContainer source;
TargetContainer target;
transform(source.begin(), source.end(), back_inserter(target), f123);

这个第二个解决方案要好得多,因为不仅代码更简单,而且更重要的是,无需中间计算,空间需求更少。

但是,f123 的组成必须在编译时确定,因此在运行时固定。

如果要在运行时确定组成,我将如何有效地做到这一点?例如,如果此代码在 RPC 服务中,并且实际组合 - 它可以是 f1f2f3< 的任何子集的任何排列--基于来自 RPC 调用的参数。

最佳答案

编辑:http://ideone.com/5GxnW 的工作版本.下面的版本有想法但不能编译。支持运行时类型检查,运行时函数组合。

这个想法是定义一个通用(一元)函数类,以及一种通过运行时类型检查组合它们的方法。这是通过 boost::anyboost::function 和类型删除习语的组合来完成的。

#include <boost/any.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>


template <typename T>
struct identity
{
T operator()(const T& x) { return x; }
};

struct any_function
{
template <typename Res, typename Arg>
any_function(boost::function<Res, Arg> f)
{
impl = make_impl(f);
}

boost::any operator()(const boost::any& x)
{
return impl->invoke(x);
}

static any_function compose(const any_function& f,
const any_function& g)
{
any_function ans;
ans.impl = compose_impl(f.impl, g.impl);
return ans;
}

template <typename T>
static any_function id()
{
using boost::function
return any_function(function<T(T)>(identity<T>()));
}

template <typename Res, typename Arg>
boost::function<Res(Arg)> to_function()
{
using boost::function;
return function<Res(Arg)>(to_function_helper(impl));
}

private:
any_function() {}

struct impl_type
{
virtual ~impl_type() {}
virtual boost::any invoke(const boost::any&) = 0;
};

boost::shared_ptr<impl_type> impl;

template <typename Res, typename Arg>
static impl_type* make_impl(boost::function<Res(Arg)> f)
{
using boost::function;
using boost::any;
using boost::any_cast;

class impl : public impl_type
{
function<Res(Arg)> f;

any invoke(const any& x)
{
const Arg& a = any_cast<Arg>(x);
return any(f(a));
}

public:
impl(function<Res(Arg)> f) : f(f) {}
};

return new impl(f);
}

impl_type* compose_impl(boost::shared_ptr<impl_type> f,
boost::shared_ptr<impl_type> g)
{
using boost::any;
using boost::shared_ptr;

class impl : public impl_type
{
shared_ptr<impl> f, g;

any invoke(const any& x)
{
return g->invoke(f->invoke(x));
}

public:
impl(const shared_ptr<impl>& f,
const shared_ptr<impl>& g)
: f(f), g(g)
{}
};

return new impl(f, g);
}

struct to_function_helper
{
template <typename Res, typename Arg>
Res operator()(const Arg& x)
{
using boost::any;
using boost::any_cast;

return any_cast<Res>(p->invoke(any(x)));
}

to_function_helper(const boost::shared_ptr<impl>& p) : p(p) {}

private:
boost::shared_ptr<impl> p;
};
};

现在,让我们使用标准算法并执行此操作(这甚至适用于空序列):

// First function passed is evaluated first. Feel free to change.
template <typename Arg, typename Res, typename I>
boost::function<Res(Arg)> pipeline(I begin, I end)
{
return std::accumulate(begin, end,
any_function::id<Arg>,
std::ptr_fun(any_function::compose)
).to_function<Res, Arg>();
}

并使用以下方法应用它

std::vector<any_function> f;
std::vector<double> v;
std::vector<int> result;

std::transform(v.begin(), v.end(),
result.begin(),
pipeline<double, int>(f.begin(), f.end())
);

你甚至可以使用 boost::transform_iterator

typedef boost::transform_iterator<
boost::function<double, int>,
std::vector<double>::const_iterator
> iterator;

boost::function<double, int> f = pipeline<double, int>(f.begin(), f.end());
std::copy(iterator(v.begin(), f), iterator(v.end(), f), result.begin());

关于C++ 迭代器流水线设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5123688/

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