C ++ How can I prevent the developers of my team from using the integer version of abs by mistake?

My team writes code to compile for both Windows (using VS2015 ) and Android (using GCC 4.9 called by QtCreator ).

We found that Android binaries had a problem with the abs function.

 double a = 1.0; double b = 0.5; std::cout << abs( a - b ) << std::endl; std::cout << std::abs( a - b ) << std::endl; 

Output:

 1 0.5 

This is a known issue found in this thread (among other things): A strange error in using abs () that I encountered recently

There are many places where we use abs , I will replace them with std::abs . Good. But how can I prevent the use of abs in the future?

Found this thread: Avoid compiler issues with abs () , but that didn't help.

I cannot allow all warnings to be treated as errors (-Werror -Wall) because g ++ is much less permissive than MSVC. Even if we make an effort to compile with 0 warning on MSVC, we still get tons of them with g ++ (there may be one among them when abs is used poorly), and we historically ignore them. Fixing them all will require a lot of effort from us.

+4
source share
3 answers

Do you have a header file that is mostly included by everyone? Some kind of holder of all the basics? If so, you can put it there:

 extern void NeverDefined(); inline int abs(int a) { NeverDefined(); return a; } // abs(int) 

If you then get a linker error on NeverDefined , you will know that there is a problem!

Usually I simply did not define this function, but since it was a library function, I had to have this second level.

Edit

Actually: do not bother the header file (a standard definition will suffice). Write your own abs.cc with the above code (no inline ) and it will replace the library definition.

Of course, this will not work if the source file marks the inline function - in this case you can always edit the original definition ...

+2
source

Do you have the opportunity to set the required compiler flags in a central location (does cmake include any other build system that you use)? If so, you can create a header file, as indicated by John, and add a compilation flag that will contain the file at the beginning of any compilation block:

MSVC : / FI <path_to_file>

GCC : -include <path_to_file>

Clang: Same as GCC

+3
source

As stated in the same related answer from your question:

  • <math.h> is responsible for abs(int)
  • <cmath> is responsible for std::abs(double)

If you have the topmost header file, just put the method below:

 template<typename T> void abs (T); 

Therefore, wherever the found abs found, a compiler error for its void will be reported as the return value. In addition, this function is not implemented to give at least a linker error.
This compiler error can be used to replace such abs() with std::abs() . For harmless abs(int) this is not expected to result in any error, since it is available in <math.h> .

Suppose you do not have a header file included in all source files, and then as a one-time exercise, you can replace each text #include<math.h> with #include<cmath> . However, this will not be full proof in all cases. For instance:

 double my_abs () { using std::abs; return abs(x - y); } 

Therefore, it is good to have a common utility header file in the entire source file as a practice. Let it be empty.

+1
source

All Articles