Reputation: 4245
I cannot seen to understand why my code does not work.
I have two vectors and I wish to substitute my second vector with the product of each element (v2[0] = v1[0] * v2[0]
, v2[1] = v1[1] * v2[1]
and so on...)
code
vector <float> vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
return std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
}
If anyone can point out my mistake, I will be very grateful.
P.S. The error message that my compiler throws is:
error: conversion from ‘__gnu_cxx::__normal_iterator<float*, std::vector<float> >’ to non-scalar type ‘std::vector<float>’ requested
P.S. 2 I am running C++98
Upvotes: 2
Views: 1413
Reputation: 93264
The error is pretty clear: std::transform
returns an iterator, you're returning a vector<float>
, which cannot be implicitly constructed by a single iterator.
Also, the overload of std::transform
that you're trying to call is not the right one, as it accepts an UnaryOperation
while std::multiplies
is a BinaryOperation
. You need this overload:
template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );
The following code will compile and work:
auto vectorMultiplication(const std::vector<float>& v1, const std::vector<float>& v2)
{
std::vector<float> result;
std::transform(v1.begin(), v1.end(), v2.begin(),
std::back_inserter(result), std::multiplies<float>());
return result;
}
Usage example:
std::vector<float> v1 = {1, 2, 3, 4};
std::vector<float> v2 = {1, 2, 3, 4};
auto vm = vectorMultiplication(v1, v2);
for(const auto& x : vm) std::cout << x << " ";
Will print:
1 4 9 16
Upvotes: 6
Reputation: 19767
The error is that return std::transform(...);
tries to return the resulting output iterator, but your function is declared to return vector<float>
. You need to work out what you actually want to return, because it's not really clear here. Maybe just void
, and remove the return
keyword completely?
But you actually want to apply the function to an element from v1
and an element of v2
at the same time. The form of transform
you are trying to use does not do this. There is another form that does, but it's going to be a bit confusing here:
std::transform(v1.begin(), // start of first input range
v1.end(), // end of first input range
v2.begin(), // start of **second input** range
v2.begin(), // start of **output** range
std::multiplies<float>());
See version 3 here.
To do this, you need to be sure that v1.size() <= v2.size()
.
Click here for a working example.
Upvotes: 0
Reputation: 206577
The problem is obvious from the compiler's error message. The return type of std::transform
is an iterator, not a container.
The call
std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
updates v2
so that its elements contain the result of the element-wise multiplications.
You may change the return value of the function to void
:
void vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
}
or return v2
:
vector <float> vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
return v2;
}
Upvotes: 0