Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::abs with std::transform not working

Tags:

c++

stl

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?

like image 424
Matt Avatar asked Dec 24 '22 08:12

Matt


1 Answers

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.

like image 64
interjay Avatar answered Dec 28 '22 08:12

interjay