2012-04-27 59 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