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

倖福魔咒の 提交于 2019-12-23 12:34:38

问题


My team is writting code to be compiled for both Windows (using VS2015) and Android (using GCC 4.9 invoked by QtCreator).

We figured out that Android binaries had a problem with 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;

Displays:

1
0.5

This is a known issue, found this topic (among others): Strange bug in usage of abs() I encountered recently

There are lots of places where we use abs, I'll replace them all by std::abs. Fine. But how can I prevent abs to be used again in the future?

Found this topic: Avoiding compiler issues with abs(), but it did not help.

I can't enable treating all warnings as errors (-Werror -Wall) because g++ is much less permissive than MSVC. Even if we make the effort to compile with 0 warning on MSVC, we still get tons of them with g++ (among them there could be one about abs being used badly) and we historically ignore them. Fixing them all would take us too much effort.


回答1:


Do you have a header file that is basically included by everything? Some kind of holder-of-all-fundamentals? If so, you can put this in there:

extern void NeverDefined();

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

If you then get a linker error on NeverDefined, you'll know there's a problem!

Normally I simply wouldn't define the function in question, but since it's a library function I had to have this second level.

Edit

In fact: don't bother with a header file (the standard definition will suffice). Write your own abs.cc with the above code (no inline) and it will supersede the library definition.

Of course, this won't work if the original file marks the function inline - in which case you could always edit the original definition...




回答2:


Do you have the possibility to set mandatory Compiler flags at a central Location (common cmake includes or whatever other build system you use)? If so, you can create a header file as indicated by John and add a compile flag that will include the file at the beginning of any compilation unit:

MSVC: /FI <path_to_file>

GCC: -include <path_to_file>

Clang: Same as GCC




回答3:


As suggested in the same linked answer from your question:

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

If you have a top-most header file then simply put below method:

template<typename T> void abs (T);

Hence, wherever there is an abs found, a compiler error will be reported for its void as return value. Additionally this function is unimplemented to give a linker error at least.
This compiler error can be used for replacing such abs() with std::abs(). For harmless abs(int), this will expectedly not generate any error as it's available in <math.h>.

Suppose, you don't have any header file included in all the source files then as a one time exercise, you may want to replace every text of #include<math.h> with #include<cmath>. However, this won't be full proof in all cases. For example:

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

Hence, it's good to have a common utility header file in all the source file as a practice. Let it be empty.



来源:https://stackoverflow.com/questions/38499142/c-how-can-i-prevent-my-team-developers-from-using-integer-version-of-abs-by-mi

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!