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.

Answer from Edward on Stack Overflow
Top answer
1 of 4
15

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.

2 of 4
10

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.

🌐
Reddit
reddit.com › r/cpp_questions › std::abs and constexpr
r/cpp_questions on Reddit: std::abs and constexpr
April 16, 2020 -

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

Discussions

std::abs and constexpr
It's not because it's not in the standard. (Not very satisfactory answer, I know) There is no technical reason that it's not though. It has been proposed as P0533. Revision 5 (06-2019) can be found here. ( Revison 0 was proposed 01-2017) There are also implementations . If you want to compare yours: template >...> constexpr auto abs(T const& x) noexcept { return x < 0 ? -x : x; } According to this stack overflow post and tested with compiler explorer GCC implements abs as constexpr since at least 4.9 (tested with 9.1) while all other compilers don't. And they don't because the standard says so. More on reddit.com
🌐 r/cpp_questions
9
27
April 16, 2020
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
🌐 r/cpp_questions
12
7
March 26, 2021
🌐
GitHub
github.com › sweeneychris › TheiaSfM › issues › 246
std::abs() not considered constexpr by clang · Issue #246 · sweeneychris/TheiaSfM
August 21, 2019 - // allowing 10 percent error for radial distortion parameters static constexpr double kRadDistThreshold1 = 0.1 * std::abs(kRadialDistortion1 * std::pow(kFocalLength1,2)); static constexpr double kRadDistThreshold2 = 0.1 * std::abs(kRadialDistortion2 * std::pow(kFocalLength2,2));
Author   holynski
🌐
Cppreference
en.cppreference.com › w › cpp › numeric › math › abs
std::abs, std::labs, std::llabs, std::imaxabs - cppreference.com
Computes the absolute value of the integer number num. The behavior is undefined if the result cannot be represented by the return type. If std::abs is called with an unsigned integral argument that cannot be converted to int by integral promotion, the program is ill-formed.
🌐
Sandor Dargo’s Blog
sandordargo.com › blog › 2023 › 05 › 24 › cpp23-constexpr
C++23: Even more constexpr | Sandor Dargo's Blog
July 19, 2023 - These headers have been simply neglected so far, otherwise, there is no reason why std::chrono::abs is constexpr but std::abs is not. In (8.E-G sections of P0533R9 you can find the full list of functions that are going to become constexpr. Luckily it’s quite a long list!
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2021 › p0533r8.pdf pdf
constexpr for
the recently added lerp is currently declared constexpr, thereby artificially restricting what can be done at · compile-time within the standard library. Furthermore, it is incongruous that, while std::chrono::abs can · be used in a constexpr context, the same is not true ·
🌐
JUCE
forum.juce.com › general juce discussion
[solved] Why does my Abs function crash but not std::abs? - General JUCE discussion - JUCE
June 2, 2018 - I hope it’s OK to ask generic C++ stuff here… I’m playing around with various optimizations and approximizations, just having fun and trying to squeeze the odd microsecond out here and there. So I wrote my own approach to a function that turns a value into its absolute (positive) value, basically to measure it against std::abs(). This is my implementation: namespace Math { template inline const TYPE Abs (const TYPE& Value) { return Value + (Value
🌐
C++ Stories
cppstories.com › 2022 › const-options-cpp20
const vs constexpr vs consteval vs constinit in C++20 - C++ Stories
November 28, 2022 - In the above scenario, constexpr means that the function can be evaluated for constant expressions, but const implies that the function won’t change its data members.
Find elsewhere
🌐
Marzer
marzer.github.io › muu › group__abs.html
Math » abs() module | muu Miscellaneous useful utilities for C++
auto abs(long double x) -> long double constexpr noexcept · Returns the absolute value of a long double.
🌐
Google Groups
groups.google.com › a › isocpp.org › g › std-proposals › c › cZXB9K59a9w
Constexpr maths functions
That would give them better control of exactly what they are doing - while the rest of us, almost every user of floating point maths, can use double in FE_DONT_KNOW_AND_DONT_CARE_AT_ALL rounding mode. Compatibility with C, and compatibility with existing programs, is of course paramount. I would propose a better compromise would be to introduce a nested namespace std::ce:: for constexpr compatible functions like std::ce::sin, std::ce::pow, std::ce::abs.
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2023 › p1383r1.pdf pdf
More constexpr for <cmath> and <complex> - Open-std.org
tential tension is more about the philosophical ques- tion of whether [Approx] functions should be usable in · a constexpr context. Strict adherents to the position of · only allowing [Canon] functions to be used in this way · may object to the first option out of principle but, again, let us emphasise that practically speaking there is no rea- son the two approaches cannot coexists.
🌐
Clang
clang.llvm.org › extra › clang-tidy › checks › modernize › use-std-numbers.html
clang-tidy - modernize-use-std-numbers — Extra Clang Tools 23.0.0git documentation
A literal matches a constant if abs(literal - constant) < DiffThreshold evaluates to true. Default is 0.001. ... A string specifying which include-style is used, llvm or google. Default is llvm. « modernize-use-std-format :: Contents :: modernize-use-std-print »
🌐
GNU
gcc.gnu.org › onlinedocs › gcc-4.7.2 › libstdc++ › api › a01013.html
libstdc++: cmath File Reference
February 14, 2020 - Go to the source code of this file · This is a Standard C++ Library file. You should #include this file in your programs, rather than any of the *.h implementation files
🌐
University of Frankfurt
itp.uni-frankfurt.de › ~sciarra › C++_User_Group › Talks › 2019_01.pdf pdf
constexpr: Introduction
constexpr_pow_int_cpp14 (double base, int exp) { if ((exp > 100) || (exp < -100)) { throw std::range_error ("abs(exp) exceeds 100"); } if (exp < 0) { base = 1.0 / base; exp = -1 * exp; } double result = 1.0; for (int i = 0; i < exp; ++i) { result *= base; } return result; } constexpr_pow_int_cpp14 ·
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2019 › p0533r5.pdf pdf
constexpr for <cmath> and <cstdlib>
JTC1/SC22/WG21 - Papers 2019 · mailing2019-01 · mailing2019-03 · mailing2019-06 · mailing2019-08 · mailing2019-10 · mailing2019-11
🌐
Stack Overflow
stackoverrun.com › it › q › 7606339
c++ - Perché non è abs constexpr?
#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.
🌐
GitHub
github.com › kthohr › gcem
GitHub - kthohr/gcem: A C++ compile-time math library using generalized constant expressions · GitHub
A C++ compile-time math library using generalized constant expressions - kthohr/gcem
Starred by 814 users
Forked by 81 users
Languages   C++ 94.4% | Jupyter Notebook 2.7% | CMake 2.2% | Makefile 0.7%
🌐
cpprefjp
cpprefjp.github.io › reference › cmath › abs.html
abs - cpprefjp C++日本語リファレンス
#include <cmath> #include <iostream> int main() { std::cout << std::fixed; std::cout << "abs(1.5) = " << std::abs(1.5) << std::endl; std::cout << "abs(-1.5) = " << std::abs(-1.5) << std::endl; } ... namespace std { constexpr float abs(float x) { return x < 0 ?
🌐
Javaer101
javaer101.com › en › article › 12507470.html
Why isn't abs constexpr? - Javaer101
October 21, 2020 - #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.