The compiler message is quite clear here: Your lambda must take one input argument, but your lambda takes two input arguments x
and y
. You simply cannot use std::transform
for your task, as std::transform
only takes single values and transforms them, not pairs of values.
Here are three possible ways of achieving your task:
Plain old imperative programming
Why not simply use the plain old non-functional way like this:
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);
}
Make sure that the size of m_vertices
is even; otherwise this code will blow up, of course.
Lamdas and functional programming are nice, but sometimes simply doing it imperatively is easier.
Writing your own pair transformation function
Here is how you could write a function that does your reduction by using a 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);
}
}
Now you can use this function with your lambda. I.e.:
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) ;
}
);
Writing a pair iterator
As Steve Jessop correctly states in his comment, writing an own pair iterator is even more flexible but also more work. It might look like this (sketch code, do not have a compiler here, might contain minor bugs):
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); }
Now you could use std::transform
like this:
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) ;
}
);