C ++将数据从浮点数向量复制到浮点对向量

时间:2014-06-29 09:48:22

标签: c++ c++11 vector

我有一个目标标准向量:

 std::vector<std::pair<float,float> > allVertices;

为什么我要使用对,因为每2个浮点数呈现位置​​对(x,y)。现在,我有一个源std :: vector,它具有所有这些位置但是作为float数组(称为m_vertices)。

我需要将所有数据从m_vertices复制到allVertices的末尾,并在复制过程中执行数据转换。

std::transform出现在我的脑海中Lambda,但我无法弄清楚如何从浮动向量到浮点对向量进行复制。

天真:

    std::transform(m_vertices.begin(),m_vertices.end(),allVertices.end(),
                [](float x,float y)->std::pair<float,float>
            {
                return std::pair<float,float>(x * 100.0f,y * 100.0f)  ;
            }
            );

给我编译时错误:

  

错误C2064:术语不评估为采用1个参数的函数

还有一些更难看的东西。

顺便说一句,如果有人可以指出如何在不需要std :: pair结构的情况下转换数据对,那么在我的情况下它会更有帮助。

更新:

由于一些使用典型迭代器的答案提议,我想强调我真的希望看到功能解决方案。如果可能的话。

2 个答案:

答案 0 :(得分:6)

编译器消息在这里很清楚:你的lambda必须使用一个输入参数,但你的lambda需要两个输入参数xy。您根本无法使用std::transform执行任务,因为std::transform只接受单个值并对其进行转换,而不是对值对。

以下是实现任务的三种可能方式:

普通的旧命令式编程

为什么不简单地使用这样简单的旧功能:

for(auto it = m_vertices.begin(); it != m_vertices.end();++it){
    float x = *it;
    ++it;
    float y = *it;
    all_vertices.emplace_back(x*100f,y*100f);
}

确保m_vertices的大小均匀;否则这段代码会爆炸。

Lamdas和函数式编程很不错,但有时候只是简单地执行它会更容易。

编写自己的对转换函数

以下是如何编写一个使用lamdba进行缩减的函数:

template< class InputIt, class OutputIt, class BinaryReducerOp >
OutputIt transformPairs( InputIt first1, InputIt last1, OutputIt d_first,
                    BinaryReducerOp reducer_op );
    for(auto it = first1; it != last1;++it){
        auto& x = *it;
        ++it;
        if(it == last1) throw; // Input length not even!
        auto& y = *it;
        *d_first++ = reducer_op(x,y);
    }
}

现在你可以在lambda中使用这个功能了。即:

  transformPairs(m_vertices.begin(),m_vertices.end(),allVertices.end(),
                [](float x,float y)->std::pair<float,float>
            {
                return std::pair<float,float>(x * 100.0f,y * 100.0f)  ;
            }
            );

编写一对迭代器

正如Steve Jessop在评论中正确指出的那样,编写自己的对迭代器更灵活,但也更有效。它可能看起来像这样(草图代码,这里没有编译器,可能包含小错误):

template<typename It> struct PairIterator {
private:
    mutable It it; // mutable so we can move around in operator*
public:
    typedef decltype(it*) Element;

    PairIterator(const It& it) : it(it) {}

    bool operator!=(const PairIterator<It>& other) const { return other != it; }

    std::pair<Element, Element> operator*() const {
        const Element& e1 = it*;
        ++it;
        const Element& e2 = it*;
        --it;
        return std::make_pair(e1,e2);
    }

    PairIterator<It>& operator++(){
        ++it;
        ++it;
        return *this;
    } 
}

template<typename It>
make_pair_it(const It& it){ return PairIterator<It>(it); }

现在你可以像这样使用std::transform

std::transform(make_pair_it(m_vertices.begin()),make_pair_it(m_vertices.end()),allVertices.end(),
                    [](std::pair<float,float> p)->std::pair<float,float>
                {
                    return std::pair<float,float>(p.first * 100.0f,p.second * 100.0f)  ;
                }
                );

答案 1 :(得分:0)

另外针对您的问题,由于两个矢量中的内存数组相同,您可以直接复制内存,这是我认为最快的解决方案。

请注意,在将此问题应用于其他案例之前,您必须确定自己正在做什么,它可能很容易成为错误的来源。如果你试图复制不同的类型(例如double to float),它将不起作用。

allVertices.resize(m_vertices.size() / 2u);
std::copy_n(m_vertices.data(), m_vertices.size(), &(allVertices.front().first));

如果m_vertices大小不均匀,则此代码也会中断。

然后,您可以简单地使用远程基础for循环来应用您的患者

for (auto & pair: allVertices)
    treatment(pair);