Avoiding compiler issues with abs()
Asked Answered
W

2

13

When using the double variant of the std::abs() function without the std with g++ 4.6.1, no warning or error is given.

#include <algorithm>
#include <cmath>

double foobar(double a)
{
     return abs(a);
}

This version of g++ seems to be pulling in the double variant of abs() into the global namespace through one of the includes from algorithm. This looks like it is now allowed by the standard (see this question), but not required.

If I compile the above code using a compiler that does not pull the double variant of abs() into the global namespace (such as g++ 4.2), then the following error is reported:

warning: passing 'double' for argument 1 to 'int abs(int)'

How can I force g++ 4.6.1, and other compilers that pull functions into the global namespace, to give a warning so that I can prevent errors when used with other compilers?

Westering answered 30/1, 2012 at 15:41 Comment(2)
What's wrong with using std::abs if that is the function you need?Freud
@JonathanLeffler Nothing, but it can be easy to miss out by mistake. I don't want that slip to go undetected and cause compilation issues with other compilers.Westering
S
8

The function you are using is actually the integer version of abs, and GCC does an implicit conversion to integer.

This can be verified by a simple test program:

#include <iostream>
#include <cmath>

int main()
{
    double a = -5.4321;
    double b = std::abs(a);
    double c = abs(a);

    std::cout << "a = " << a << ", b = " << b << ", c = " << c << '\n';
}

Output is:

a = -5.4321, b = 5.4321, c = 5

To get a warning about this, use the -Wconversion flag to g++. Actually, the GCC documentation for that option explicitly mentions calling abs when the argument is a double. All warning options can be found here.

Stopping answered 30/1, 2012 at 15:56 Comment(3)
@SamDeHaan Sorry, updated result but forgot to update the code. :)Stopping
Is it the standard that has changed or a change in g++'s implementation that causes the implicit conversion with 4.6.1 and not 4.2? Are both valid?Westering
The above code doesn't compile with my version of g++ (4.4.2). If I add an #include <math.h> it will, however. And VC++ (VS 2010) calls the double version of abs. (I think this is actually the point of the original posting. The behavior is very varied.) Formally, it shouldn't compile in C++03; whether it compiles in C++11 is implementation defined. In practice, however, there's always been a great deal of variation across implementations.Insomuch
O
1

Be warned, you don't need to explicitly #include <cmath>, <iostream> does the damage as well (and maybe some other headers). Also, note that -Wall doesn't give you any warnings about it.

#include <iostream>

int main() {
  std::cout << abs(.5) << std::endl;
  std::cout << typeid(decltype(abs)).name() << std::endl;
}

Gives output

0
FiiE

On

gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04) 
Occupation answered 30/5, 2019 at 8:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.