Take this example:
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cmath>
void PrintVec(const std::vector<float>&);
int main(int argc, char * argv[]){
float vals[] = {-1.2,0.0,1.2};
std::vector<float> test(vals, vals + sizeof(vals) / sizeof(float));
std::vector<float> absTest(3);
std::transform(test.begin(), test.end(), absTest.begin(), std::abs<float>());
PrintVec(test);
PrintVec(absTest);
return 0;
}
void PrintVec(const std::vector<float> &vec){
for (unsigned int i = 0; i < vec.size(); ++i){
std::cout << vec[i] << '\n';
}
return;
}
Using both gcc 4.3.4 and VS 2013 I get compiler errors. For gcc its:
testTransformAbs.cpp:15: error: expected primary-expression before 'float'
For VS 2013 its:
error C2062: type 'float' unexpected
If I remove <float>
then I get this error:
testTransformAbs.cpp:15: error: no matching function for call to 'abs()' /usr/include/stdlib.h:766: note: candidates are: int abs(int) /usr/include/c++/4.3/cstdlib:144: note: long int std::abs(long int) /usr/include/c++/4.3/cstdlib:175: note: long long int __gnu_cxx::abs(long long int) /usr/include/c++/4.3/cmath:99: note: double std::abs(double) /usr/include/c++/4.3/cmath:103: note: float std::abs(float) /usr/include/c++/4.3/cmath:107: note: long double std::abs(long double)
I can create my own function
float MyAbs(float f){
return sqrt(f * f);
}
std::transform(test.begin(), test.end(), absTest.begin(), MyAbs);
And everything works. The reference on cplusplus.com says that the fourth input can be an UnaryOperation defined by:
Unary function that accepts one element of the type pointed to by InputIterator as argument, and returns some result value convertible to the type pointed to by OutputIterator. This can either be a function pointer or a function object.
To me this should be able to use std::abs()
. I also tried fabs
with the same result. What am I missing?
std::abs
is an overloaded function, not a template function. When obtaining a pointer to the function, you can choose a specific overload by casting:
std::transform(test.begin(), test.end(), absTest.begin(),
static_cast<float (*)(float)>(&std::abs));
or by using a function pointer variable:
float (*fabs)(float) = &std::abs;
std::transform(test.begin(), test.end(), absTest.begin(), fabs);
Note that I also removed the ()
you put after abs
, since this is a function and not a class that needs to be instantiated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With