我正在处理一个循环在一个潜在的多维数组上的东西,我遇到了一些模板问题。以下是我尝试做的事情:
template<std::size_t D = 3>
class Deriv {
public:
typedef typename boost::array<double, D> results_t;
template<typename Iterator>
results_t operator()(Iterator& objIterator)
{
double u;
double um1;
results_t derivs;
for(results_t::index i = 0; i < D; ++i) {
u = *objIterator;
um1 = *(objIterator.left<i>(1));
derivs[i] = u-um1;
}
}
};
};
所以,它看起来有点令人困惑,但它使用的是具有left
和right
模板方法的自定义迭代器,其中模板参数是向左或向右移动的维度而参数是偏移量。例如,如果objIterator
指向array[i][j][k]
,则objIterator.left<0>(1)
会将迭代器返回array[i-1][j][k]
。
显然我发布的内容并不起作用,因为i
不是编译时间,不能用作left
的参数。我觉得这里可以使用递归来某种方式通过替换for循环来实现这一点,但我不知道如何。
有什么建议吗?
答案 0 :(得分:2)
这是另一种方法:
template<std::size_t D = 3>
struct Deriv
{
typedef typename boost::array<double, D> results_t;
private:
template<std::size_t I>
struct apply
{
template<typename Iterator>
static void impl(results_t& derivs, Iterator& iter)
{
derivs[I] = *iter - *iter.template left<I>(1);
apply<I + 1>::impl(derivs, iter);
}
};
template<>
struct apply<D>
{
template<typename Iterator>
static void impl(results_t&, Iterator&) { }
};
public:
template<typename Iterator>
results_t operator ()(Iterator& iter) const
{
results_t derivs;
apply<0>::impl(derivs, iter);
return derivs;
}
};
我已经使用VC ++ 2010进行了测试,但我怀疑它可能无法在更符合标准的编译器上进行编译。如果您可以从D-1
到0
而不是从0
到D-1
倒计时,那么以下情况应该没问题:
namespace detail
{
template<std::size_t I>
struct apply
{
template<typename ResultsT, typename Iterator>
static void impl(ResultsT& derivs, Iterator& iter)
{
derivs[I] = *iter - *iter.template left<I>(1);
apply<I - 1>::impl(derivs, iter);
}
};
template<>
struct apply<0>
{
template<typename ResultsT, typename Iterator>
static void impl(ResultsT& derivs, Iterator& iter)
{
derivs[0] = *iter - *iter.template left<0>(1);
}
};
}
template<std::size_t D = 3>
struct Deriv
{
typedef typename boost::array<double, D> results_t;
public:
template<typename Iterator>
results_t operator ()(Iterator& iter) const
{
results_t derivs;
detail::apply<D - 1>::impl(derivs, iter);
return derivs;
}
};
答案 1 :(得分:0)
我没有方便的C ++编译器,但这应该可以解决您的问题:
template<typename Iterator, int dimNo>
void processDim(results_t & derivs, Iterator& objIterator) {
if(dimNo==-1) return;
double u;
double um1;
u = *objIterator;
um1 = *(objIterator.left<dimNo>(1));
derivs[dimNo] = u-um1;
processDim<Iterator,dimNo!=D?dimNo+1:-1>(derivs, objIterator);
}
template<typename Iterator>
results_t operator()(Iterator& objIterator)
{
results_t derivs;
processDim<Iterator, 0> (derivs,objIterator);
return derivs;
}
你的代码也有隐藏的笑脸!
顺便说一句,如果你能够修改即将到来的Iterator
类型,你可以让它接收维度作为常规参数(不是模板参数),如果它是模板参数的唯一原因是性能首先。我确信编译器会发现它可以简单地展开循环。这样,您就不需要任何丑陋的递归模板。
答案 2 :(得分:0)
一般的想法,根据你的需要修改它。
// recursive
template<typename Iterator, int I>
void apply(Iterator& objIterator, results_t &derivs, mpl::int_<I>) {
u = *objIterator;
um1 = *(objIterator.left<I>(1));
derivs[I] = u-um1;
apply(objIterator, derivs, mpl::int_<I-1>());
}
// terminate
template<typename Iterator>
void apply(Iterator& objIterator, results_t &derivs, mpl::int_<-1>) {}
另请参阅http://www.boost.org/doc/libs/1_45_0/libs/mpl/doc/refmanual/for-each.html