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

leftそのため、少し混乱しているように見えますが、テンプレート パラメータが左または右に移動するディメンションであり、引数がオフセットであるandrightテンプレート メソッドを持つカスタム イテレータを使用しています。たとえば、 がobjIteratorを指している場合は、イテレータを に返しarray[i][j][k]ます。objIterator.left<0>(1)array[i-1][j][k]

iコンパイル時ではなく、のパラメーターとして使用できないため、明らかに私が投稿したものは機能しませんleft。ここで再帰を使用して、forループを置き換えることでこれを実現できると思いますが、その方法はわかりません。

助言がありますか?

4

3 に答える 3

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からカウントダウンできる場合は、次のように問題ありません。00D-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;
    }
};
于 2012-04-27T19:21:37.590 に答える
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もご覧ください。

于 2012-04-27T19:22:33.653 に答える
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今後の型を変更できる場合は、ディメンションがテンプレート パラメータである唯一の理由がそもそもパフォーマンスのためである場合、(テンプレート パラメータではなく) 通常の引数としてディメンションを受け取るようにすることができます。コンパイラーは、ループを単純に展開できることを理解すると確信しています。このように、醜い再帰的なテンプレートは必要ありません。

于 2012-04-27T19:16:12.067 に答える