I've come across a few different examples of ways in which std::abs can give unexpected results:
- This question (On the std::abs function) points out that
<cstdlib>provides overloads for integral types while<cmath>provides overloads for floating point types. Failing to include the correct header gives undefined behaviour, which the compiler is allowed to silently accept - C++ Defect report 2735 points out that the C++11 and C++14 standards technically require that
std::abs(short)returns adouble, although most compilers ignore the relevant wording and return anint. The resolution to this issue indicates that the wording was changed in C++17 so thatstd::abs(short)returns anint - The answers to this question (When do I use fabs and when is it sufficient to use std::abs?) point out that relying on
std::abscan lead to difficult-to-spot bugs, since (in modern C++) the headers which introducestd::absare allowed to introduce a globalabsfunction (which may or may not have the same overloads), and it's easy to accidentally useabsinstead ofstd::abs
The fixes that I am aware of are:
- Avoid undefined behaviour: include
<cstdlib>if evaluatingstd::abs([integral type])and<cmath>if evaluatingstd::abs([floating point type]) - Two options:
- Use C++17 or pre-(C++11)
- Work around the fact that
std::abs(short)may return anintor adoubledepending on the compiler's compliance with the C++11/C++14 standard
- Two options:
- Pass gcc the flag
–Wconversionso that calls likeabs(2.0)trigger a warning at compilation - Use a trick (adapted from n.m.'s answer to (Disable math.h crap when working with cmath)) to make to the global
absambiguous
- Pass gcc the flag
Trick:
namespace neveruse{
int abs(int);
}
using namespace neveruse;
Question: Is there a reason to prefer one of the solutions to issue 3 over the other? Do any of these fixes introduce other potential problems that I need to watch out for?