2012-04-27 91 views
4

我正在处理可能会在多维数组上循环的内容,并且遇到了一些模板问题。这里是我想要做的想法:用于循环替换的模板

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; 
     } 
    } 
    }; 
}; 

因此,它看起来有点混乱,但它的使用具有leftright模板方法,其中的模板参数是尺寸为自定义迭代器向左或向右移动,参数是偏移量。例如,如果objIterator指向array[i][j][k],则objIterator.left<0>(1)会将迭代器返回到array[i-1][j][k]

很明显我发布的内容不起作用,因为i不是编译时间,不能用作left的参数。我觉得在这里可以使用递归来通过替换for循环来实现这一点,但我不知道如何。

有什么建议吗?

回答

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进行测试,但我怀疑它可能无法编译更多符合标准的编译。如果你可以通过0而不是向上从0通过D-1D-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; 
    } 
}; 
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类型即将到来,您可以使它作为常规参数(不是模板参数)接收维度,如果它是模板参数的唯一原因是为了第一个性能地点。我确信编译器会发现它可以简单地展开循环。这样,你不需要任何丑陋的递归模板。

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

+0

@ildjarn它看起来像它,但它不是。这是:'模板无效申请(' – Anycorn 2012-04-27 19:51:36

+0

是的,我意识到,提交后的评论和删除它不久后: - ] – ildjarn 2012-04-27 19:52:56

+0

@ildjarn浩伤害 – Anycorn 2012-04-27 19:55:51