Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I avoid unexpected results from std::abs?

I've come across a few different examples of ways in which std::abs can give unexpected results:

  1. 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
  2. C++ Defect report 2735 points out that the C++11 and C++14 standards technically require that std::abs(short) returns a double, although most compilers ignore the relevant wording and return an int. The resolution to this issue indicates that the wording was changed in C++17 so that std::abs(short) returns an int
  3. 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::abs can lead to difficult-to-spot bugs, since (in modern C++) the headers which introduce std::abs are allowed to introduce a global abs function (which may or may not have the same overloads), and it's easy to accidentally use abs instead of std::abs

The fixes that I am aware of are:

  1. Avoid undefined behaviour: include <cstdlib> if evaluating std::abs([integral type]) and <cmath> if evaluating std::abs([floating point type])
  2. Two options:
    • Use C++17 or pre-(C++11)
    • Work around the fact that std::abs(short) may return an int or a double depending on the compiler's compliance with the C++11/C++14 standard
  3. Two options:
    • Pass gcc the flag –Wconversion so that calls like abs(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 abs ambiguous

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?

like image 461
user1476176 Avatar asked May 05 '18 23:05

user1476176


1 Answers

Create a header file of your own that defines an inline functionabsolute that in turn includes all the correct headers and fixes bugs with return types, and calls std::abs.

Then, don't use abs or std::abs (or any token named abs). Enforce this at git commit (or whatever version management system you are using) other than in that file.

like image 76
Yakk - Adam Nevraumont Avatar answered Sep 20 '22 08:09

Yakk - Adam Nevraumont