C ++ / STL:带有给定步幅的std :: transform?

时间:2010-03-19 10:21:18

标签: c++ stl transform foreach

我有一个包含Nd数据的1d数组,我想用std :: transform或std :: for_each有效地遍历它。

unigned int nelems;
unsigned int stride=3;// we are going to have 3D points
float *pP;// this will keep xyzxyzxyz...
Load(pP);
std::transform(pP, pP+nelems, strMover<float>(pP, stride));//How to define the strMover??

4 个答案:

答案 0 :(得分:3)

答案不是改变strMover,而是改变你的迭代器。定义一个新的迭代器类,它包装float *但在调用operator++时向前移动3个位置。

你可以使用boost Permutation Iterator并使用非严格排列,只包括你感兴趣的范围。

如果你试图推出自己的迭代器,那么有一些问题:要保持对标准的严格要求,你需要仔细考虑这种步长迭代器的正确“结束”迭代器是什么,因为天真的实现会很快乐超越允许的“一个接一个的结束”到远远超过阵列末端的阴暗区域,指针永远不会进入,因为害怕nasal demons

但我不得不问:为什么你首先将一个3d点数组存储为float s的数组?只需定义一个Point3D数据类型,然后创建一个数组。更简单。

答案 1 :(得分:1)

好吧,我决定使用for_each而不是转换任何其他决定是受欢迎的:

generator<unsigned int> gen(0, 1);
            vector<unsigned int> idx(m_nelem);//make an index
            std::generate(idx.begin(), idx.end(),gen);
            std::for_each(idx.begin(), idx.end(), strMover<float>(&pPOS[0],&m_COM[0],stride));

,其中

template<class T> T op_sum (T i, T j) { return i+j; }
template<class T> 
class strMover
    {
    T *pP_;
    T *pMove_;
    unsigned int stride_;
    public:
        strMover(T *pP,T *pMove, unsigned int stride):pP_(pP), pMove_(pMove),stride_(stride)
            {}
        void operator() ( const unsigned int ip )
            {
            std::transform(&pP_[ip*stride_], &pP_[ip*stride_]+stride_, 
                pMove_, &pP_[ip*stride_], op_sum<T>);
            }
    };

从第一眼看,这是一个线程安全的解决方案。

答案 2 :(得分:1)

这很可怕,人们告诉你使用步幅迭代器。除了不能使用这种方法从标准库中使用功能对象之外,编译器通过使用这样的拐杖来生成多核或sse优化非常非常复杂。 寻找“stride iterator”以获得正确的解决方案,例如在c ++ cookbook中。

回到原始问题...使用valarray和stride来模拟多维数组。

答案 3 :(得分:0)

使用升压适配器。你可以从它们中获取迭代器。唯一的缺点是编译时间。

vector<float> pp = vector_load(pP);
boost::for_each(pp|stride(3)|transformed(dosmtn()));