【问题标题】:Template for loop replacement循环替换模板
【发布时间】:2012-04-27 19:00:45
【问题描述】:

我正在处理可能在多维数组上循环的东西,但遇到了一些模板问题。这是我想要做的事情的想法:

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&lt;0&gt;(1) 返回一个指向array[i-1][j][k] 的迭代器。

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

有什么建议吗?

【问题讨论】:

    标签: c++ templates recursion


    【解决方案1】:

    这是另一种方法:

    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-10 倒计时而不是从0D-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;
        }
    };
    

    【讨论】:

      【解决方案2】:

      我手边没有 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 类型,那么如果它是模板参数的唯一原因是为了在第一名。我相信编译器会发现它可以简单地展开循环。这样,您就不需要任何丑陋的递归模板。

      【讨论】:

        【解决方案3】:

        总体思路,根据您的需要进行修改。

        // 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

        【讨论】:

        • @ildjarn 看起来像,但不是。这是:template&lt;typename T&gt;void apply&lt;T&gt;(
        • 是的,我在提交评论后不久意识到并删除了它。 :-]
        猜你喜欢
        • 1970-01-01
        • 2014-09-30
        • 1970-01-01
        • 2022-01-14
        • 2011-09-22
        • 2019-04-04
        • 2018-08-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多