This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

2294. <cstdlib> should declare abs(double)

Section: 29.7 [c.math] Status: Resolved Submitter: Pete Becker Opened: 2013-09-04 Last modified: 2017-03-12

Priority: 2

View all other issues in [c.math].

View all issues with Resolved status.

Discussion:

… and abs(float) and abs(long double). And <cmath> should declare abs(int), abs(long), and abs(long long).

As things currently stand, this program is illegal:

#include <cstdlib>

int main() {
  double d = -1.23;
  double dd = std::abs(d);
  return 0;
}

The call is ambiguous because of the various integer overloads, that's because <cstdlib> provides abs(int) but not abs(double).

This lead one commenter on Stackoverflow to state that abs is dangerous, and to recommend using fabs instead.

In general, it makes sense to declare overloaded functions that take user-defined types in the same header as the definition of the user-defined types; it isn't necessary to declare all of the overloads in the same place. But here we're not dealing with any user-defined types; we're dealing with builtin types, which are always defined; all of the overloads should be defined in the same place, to avoid mysterious problems like the one in the code above.

The standard library has six overloads for abs:

int abs(int);  // <cstdlib>
long abs(long); // <cstdlib>
long long abs(long long); // <cstdlib>

float abs(float); // <cmath>
double abs(double); // <cmath>
long double abs(long double); // <cmath>

These should all be declared in both headers.

I have no opinion on <stdlib.h> and <math.h>.

[2013-09 Chicago]

This issue is related to LWG 2192(i)

Move to open

[2014-02-13 Issaquah — Nicolai Josuttis suggest wording]

[2015-03-03, Geoffrey Romer provides improved wording]

See proposed resolution of LWG 2192(i).

[2015-09-11, Telecon]

Geoff provided combined wording for 2192(i) after Cologne, Howard to provide updated wording for Kona.

Howard: my notes say I wanted to use is_unsigned instead of 'unsigned integral type'.

Previous resolution from Nicolai [SUPERSEDED]:
  1. Edit 29.7 [c.math] after p7 as indicated:

    -6- In addition to the int versions of certain math functions in <cstdlib>, C++ adds long and long long overloaded versions of these functions, with the same semantics.

    -7- The added signatures are:

    long abs(long);                    // labs()
    long long abs(long long);          // llabs()
    ldiv_t div(long, long);            // ldiv()
    lldiv_t div(long long, long long); // lldiv()
    

    -?- To avoid ambiguities, C++ also adds the following overloads of abs() to <cstdlib>, with the semantics defined in <cmath>:

    float abs(float);
    double abs(double);
    long double abs(long double);
    

    -?- To avoid ambiguities, C++ also adds the following overloads of abs() to <cmath>, with the semantics defined in <cstdlib>:

    int abs(int);
    long abs(long);
    long long abs(long long);
    

[2015-08 Chicago]

Resolved by 2192(i)

Proposed resolution:

See proposed resolution of LWG 2192(i).