'Why isn't abs constexpr?

In <cinttypes>, since C++11, there are the following two overloads:

std::intmax_t abs( std::intmax_t n );
std::intmax_t imaxabs( std::intmax_t n );

Why aren't those two functions constexpr?



Solution 1:[1]

I can't give a good reason for why abs couldn't be constexpr and apparently neither can gcc. When I use gcc 4.9.2 with this program:

#include <cstdlib>
#include <cinttypes>
#include <cassert>

constexpr intmax_t abs3 = std::abs(3);
constexpr intmax_t absneg3 = std::abs(-3);
int main()
{
    assert(abs3 == absneg3);
}

it compiles and runs to completion with no warnings or errors. You can try it here. However, clang++ (version 3.5.0) throws a compile-time error:

abs.cpp:6:20: error: constexpr variable 'abs3' must be initialized by a constant expression.

I think that clang++ actually gets it right here, because in section 27.9.2 [c.files] of the 2011 standard, it says:

The contents of header are the same as the Standard C Library header , with the following changes:

— the header includes the header instead of , and

— if and only if the type intmax_t designates an extended integer type (3.9.1), the following function signatures are added:

intmax_t abs(intmax_t);

imaxdiv_t div(intmax_t, intmax_t);

which shall have the same semantics as the function signatures intmax_t imaxabs(intmax_t) and imaxdiv_t imaxdiv(intmax_t, intmax_t), respectively.

In the current working draft of the C++ standard, as in the published 2014 version, it says in section 17.6.5.6 [constexpr.functions]:

This standard explicitly requires that certain standard library functions are constexpr (7.1.5). An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.

So the result, for now, is that these functions are still not constexpr according to the standard (which you knew) but they could be, as demonstrated by the gcc compiler.

Solution 2:[2]

It has been proposed in P0533:

A function in <cmath> shall be declared constexpr if and only if:

  1. When taken to act on the set of rational numbers, the function is closed (excluding division by zero);
  2. The function does not modify any of its arguments which have external visibility;
  3. The function is not strongly dependent on the rounding mode.

By means of a brief illustration, abs satisfies all three criteria; however, functions such as exp, sqrt, cos, sin fall foul of the first criterion and so are excluded as constexpr candidates. Finally, as discussed above, nearbyint fails the final criterion.

Solution 3:[3]

The simple explanation is probably that nobody went through every function listed as part of the standard library, and updated the entry to make it constexpr.

Updating a standard is a process involving human effort to propose changes and get those proposals reviewed and accepted. And that means, when a new feature is added - and constexpr is a new feature - not everything else is automagically updated to use that feature. This particular case may well be updated in a future evolution of the standard - if some people take on the - often thankless - task of proposing the set of changes, some other people take on the task of reviewing it, and convincing those with voting power on the committee to accept it.

Solution 4:[4]

It is constexpr since C++23

long      abs( long n ); (2)    (constexpr since C++23)

https://en.cppreference.com/w/cpp/numeric/math/abs

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Edward
Solution 2 leek
Solution 3 Peter
Solution 4 Mikhail