NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: C++ language lawyer Q: requirements for bare abs()?



On Tue, 6 May 2025 at 09:14, Greg Troxel <gdt%lexort.com@localhost> wrote:
>
> I recently had trouble with code in proj, which used abs() from C++,
> expecting it to be double instead of int.  Changing to std::abs() fixed
> it.
>
> That brought up the question of what the rules are.  In C, abs() is
> solidly integer:
>
>      #include <stdlib.h>
>
>      int
>      abs(int x);
>
> and there is fabs()
>
>      #include <math.h>
>
>      double
>      fabs(double x);
>
> But C++ is different.  The standard approach is <cmath> and std::abs(),
> but I find claims that C++11 requires that <cmath> make (bare) abs()
> overloaded, and claims that C++11 permits but does not require it.

The "accepted answer" claims that in C++11+ <cmath> may expose std::abs;.
Looking at your results it seems that LLVM+? did this, but GCC+GLIBCXX
did not (which probably explains why the standard says what it says).

Here NetBSD can hide behind debian.

For <math.h>.  The linux's have a the glibc++ with its local copy of
<math.h> that I think, reduces to:

# include <cmath>
use std::abs;

the results show both CLANG+? and GCC+glibc++ agreeing on this quirk.

I suspect NetBSD may be able to argue the moral high ground, but
that's little use.

BTW, the "accepted answer"'s suggestion of using <stdlib.h> and abs()
is just as broken as <math.h>.

> In practice, it seems clear that the only reasonable coding approach is
> to include <cmath> and then use std::abs() but the standards question
> remains.

Agreed.

> I found a test program, enhanced it, and ran it on 5 systems, with
> varying results.
>
> Is NetBSD wrong here?   Or is not overloading abs() permissible?
> Is Debian wrong?

How is "none" compiling?  Presumably #include <iostream> is up to no
good, see appended.

> c++ -Wall cpp_abs.cpp; ./a.out
>
>                 none    math.h  cmath   both    both/R
>  NetBSD/gcc7    1       1       1       1       1
>  NetBSD/gcc10   1       1       1       1       1
>  Debian/gcc12   1       1.5     1       1.5     1.5

Alpine (musl) and Fedora with newer GCC's match this, see appended.

>  macOS 10.13    DNC     DNC     1.5     1.5     1.5

clang <= 18?  based on appended; also freebsd with clang

>  macOS 13       1.5     1.5     1.5     1.5     1.5

clang >18?  but could be a a header change

--

Alpine and fedora with much newer GCCs
[root@alpine source]# g++ -Wall -Wextra -Werror abs.cc && ./a.out
abs.cc: In function 'void abses(double, double*, double*)':
abs.cc:21:9: error: 'abs' was not declared in this scope
   21 |   *ax = abs(x);
      |         ^~~
abs.cc:22:15: error: 'abs' is not a member of 'std'
   22 |   *sax = std::abs(x);
      |               ^~~
[root@alpine source 1]# g++ -Wall -Wextra -Werror abs.cc -DUSE_MATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@alpine source]# g++ -Wall -Wextra -Werror abs.cc -DUSE_CMATH && ./a.out
x=-1.5 ax=1 sax=1.5
[root@alpine source]# g++ -Wall -Wextra -Werror abs.cc
-DUSE_MATH_CMATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@alpine source]# g++ -Wall -Wextra -Werror abs.cc
-DUSE_CMATH_MATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@alpine source]# g++ --version
g++ (Alpine 14.2.0) 14.2.0
cagney@fedora:~$ c++ --version
c++ (GCC) 15.1.1 20250425 (Red Hat 15.1.1-1)

[root@freebsd source]# c++ -Wall -Wextra -Werror abs.cc && ./a.out
abs.cc:21:9: error: use of undeclared identifier 'abs'
   21 |   *ax = abs(x);
      |         ^
abs.cc:22:10: error: use of undeclared identifier 'std'
   22 |   *sax = std::abs(x);
      |          ^
2 errors generated.
[root@freebsd source 1]# c++ -Wall -Wextra -Werror abs.cc -DUSE_MATH && ./a.out
abs.cc:22:10: error: no member named 'abs' in namespace 'std'; did you
mean simply 'abs'?
   22 |   *sax = std::abs(x);
      |          ^~~~~~~~
      |          abs
/usr/include/c++/v1/stdlib.h:127:64: note: 'abs' declared here
  127 | _LIBCPP_NODISCARD_EXT inline _LIBCPP_HIDE_FROM_ABI long double
abs(long double __lcpp_x) _NOEXCEPT {
      |                                                                ^
1 error generated.
[root@freebsd source 1]# c++ -Wall -Wextra -Werror abs.cc -DUSE_CMATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@freebsd source]# c++ -Wall -Wextra -Werror abs.cc
-DUSE_MATH_CMATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@freebsd source]# c++ -Wall -Wextra -Werror abs.cc
-DUSE_CMATH_MATH && ./a.out
x=-1.5 ax=1.5 sax=1.5
[root@freebsd source]# c++ --version
FreeBSD clang version 18.1.6 (https://github.com/llvm/llvm-project.git
llvmorg-18.1.6-0-g1118c2e05e67)

#ifdef USE_MATH
#include <math.h>
#endif

#ifdef USE_CMATH
#include <cmath>
#endif

#ifdef USE_MATH_CMATH
#include <math.h>
#include <cmath>
#endif

#ifdef USE_CMATH_MATH
#include <cmath>
#include <math.h>
#endif

static void abses(double x, double *ax, double *sax)
{
  *ax = abs(x);
  *sax = std::abs(x);
}

#include <iostream>

int main(int, const char *[])
{
  double x = -1.5;
  double ax;
  double sax;
  abses(x, &ax, &sax);

  std::cout << "x=" << x << " ax=" << ax << " sax=" << sax << std::endl;
  return 0;
}


Home | Main Index | Thread Index | Old Index