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.
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.
It has been proposed in P0533:
A function in
<cmath>shall be declaredconstexprif and only if:
- When taken to act on the set of rational numbers, the function is closed (excluding division by zero);
- The function does not modify any of its arguments which have external visibility;
- The function is not strongly dependent on the rounding mode.
By means of a brief illustration,
abssatisfies all three criteria; however, functions such asexp,sqrt,cos,sinfall foul of the first criterion and so are excluded asconstexprcandidates. Finally, as discussed above,nearbyintfails the final criterion.
Hi everyone,
I hope you are doing fine in those trouble time.
I came here because, in a program I working on, I wanted to see how much I could `constexpr` all the things, and I ended with `std::abs` restricted me.
Indeed, the function `std::abs` is not `constexpr`, but it seems that it could be, I experimented a bit on godbolt.
Is there a reason why `std::abs` is not `constexpr` in C++17, and maybe not in C++20 either ?
Thank you in advance for you answers :)
Link to std::abs documentation
std::abs and constexpr
Why isn't std::abs constexpr?
There was actually a proposal to change all cmath functions to constexpr which many liked, ISO is now trying to get this to c++23. There are some problems though (exceptions and the fact that these functions are ISO C's territory)
More on reddit.com