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

[solved] Why does my Abs function crash but not std::abs? - General JUCE discussion - JUCE
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, ... More on forum.juce.com
🌐 forum.juce.com
0
June 2, 2018
c++ - Generic absolute value function - Code Review Stack Exchange
If the type is a built-in floating-point, use std::abs from . If the type is a user-defined type with a namespace-level abs, use it. Otherwise, call a generic abs algorithm. ... #include #include namespace math { namespace detail { // generic abs algorithm template constexpr ... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
August 15, 2014
c++ - std::abs can be used in constexpr function, but only if it's templated. Why? - Stack Overflow
Supposedly std::abs is not constexpr in the standard (even in C++20). But in practice I found out that I can compile it as constexpr under the very peculiar condition that the function is templated... More on stackoverflow.com
🌐 stackoverflow.com
October 6, 2020
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
🌐
GitHub
github.com › sweeneychris › TheiaSfM › issues › 246
std::abs() not considered constexpr by clang · Issue #246 · sweeneychris/TheiaSfM
August 21, 2019 - src/theia/sfm/estimators/estimate_radial_distortion_homography_test.cc:73:25: error: constexpr variable 'kRadDistThreshold1' must be initialized by a constant expression static constexpr double kRadDistThreshold1 = ^ src/theia/sfm/estimators/estimate_radial_distortion_homography_test.cc:74:11: note: non-constexpr function 'abs' cannot be used in a constant expression 0.1 * std::abs(kRadialDistortion1 * std::pow(kFocalLength1, 2)); ^ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/math.h:737:1: note: declared here abs(double __lcpp_x) _NOEXCEPT {return ::fabs(__lcpp_x);} ^
Author   holynski
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2021 › p0533r8.pdf pdf
constexpr for <cmath> and <cstdlib>
June 22, 2021 - TABLE II. Various functions declared in [cmath.syn] which ... TABLE III. Absolute values declared in [cmath.syn] which
🌐
Marzer
marzer.github.io › muu › group__abs.html
Math » abs() module | muu Miscellaneous useful utilities for C++
auto abs(_Float16 x) -> _Float16 constexpr noexcept · Returns the absolute value of a _Float16. auto abs(signed char x) -> signed char constexpr noexcept
🌐
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
🌐
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.
🌐
Cppreference
en.cppreference.com › w › cpp › numeric › math › abs
std::abs, std::labs, std::llabs, std::imaxabs - cppreference.com
March 14, 2025 - 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.
Find elsewhere
🌐
cpprefjp
cpprefjp.github.io › reference › complex › complex › abs.html
abs - cpprefjp C++日本語リファレンス
namespace std { template <class T> T abs(const complex<T>& x); // (1) C++03 template <class T> constexpr T abs(const complex<T>& x); // (1) C++26 } 複素数値の絶対値(大きさ・マグニチュード)を得る。abs は absolute value(絶対値)の略。 ·
🌐
Sandor Dargo’s Blog
sandordargo.com › blog › 2023 › 05 › 24 › cpp23-constexpr
C++23: Even more constexpr | Sandor Dargo's Blog
July 19, 2023 - Until now, <cmath> and <cstdlib> has barely contained any constexpr functions. P0533R9 aims to improve on this situation in order to facilitate compile-time programming. These headers have been simply neglected so far, otherwise, there is no reason why std::chrono::abs is constexpr but std::abs is not.
🌐
GitHub
github.com › gcc-mirror › gcc › blob › master › libstdc++-v3 › include › bits › std_abs.h
gcc/libstdc++-v3/include/bits/std_abs.h at master · gcc-mirror/gcc
// 2735. std::abs(short), std::abs(signed char) and others should return int · · #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO · inline _GLIBCXX_CONSTEXPR double · abs(double __x) { return __builtin_fabs(__x); } · inline _GLIBCXX_CONSTEXPR float · abs(float __x) { return __builtin_fabsf(__x); } ·
Author   gcc-mirror
Top answer
1 of 1
2

For a regular function the compiler may know, based on the type of the function parameters, if the inner code can be potentially evaluated in compile time. This is why you get an error for calling std::abs in MSVC and clang. The behavior of gcc is based on its decision to implement std::abs as constexpr which is by the way a questionable decision.

For a template function the compiler cannot know if the inner code can be evaluated in compile time, as it may be based on the actual type of the template arguments, with different functions overload being called. While most compilers would decide not to check whether all possible overloads of std::abs cannot be constexpr, thus letting the code pass compilation, theoretically a compiler may check (in very specific cases that can be checked, like this one) and since the user is not allowed to extend std by adding a new version of abs (the list of allowed extensions to std is closed by the spec) it is possible to see that the function can never be constexpr and thus to generate a compilation error. In the more general case however, the compiler cannot check for a template function if all possible cases cannot produce a constexpr function, since it sees only the available overloads for the inner call, per each call to the template function, and there might be other available overloads for the inner call, when the template is called elsewhere.


Note that making a constexpr function a template, just so it can get compiled, would not be a good approach. The actual decision if the function is constexpr (i.e. can be called in compile time) would be based on the actual call, and if in all cases the function cannot be constexpr you are trying in a way to cheat the compiler but eventually are cheating mainly yourself...


By the way, in my check with clang 10.1 and trunk versions, I don't get compilation error on the template version, this code compiles both with gcc and clang:

template<typename T>
constexpr T myabs(T t) {
    return std::abs(t);
}

int main() {
    int i = myabs(3);
}

While this compiles with gcc (which implements std::abs as constexpr) and fails with clang:

int main() {
    constexpr int i = myabs(3);
}

It seems that both gcc and clang do not generate an error even if the inner call inside a constexpr template function is not dependent on the template parameters and can never be a constant expression:

int myabs() {
    return 42;
}

template<class T>
constexpr int f() {
    // this is never a contexpr
    // yet gcc and clang are ok with it
    return myabs();
}

And again, this is allowed as no diagnostic is required for non-conforming constexpr template functions:

[dcl.constexpr] 9.2.5/7 - The constexpr and consteval specifiers:

[...] If no specialization of the template would satisfy the requirements for a constexpr function when considered as a non-template function, the template is ill-formed, no diagnostic required.

🌐
C++ Programming Language
cpp-lang.net › standard library › mathematical functions › abs
Abs | C++ Programming Language
// 1) int abs (int n); // 2) long int abs (long int n); // 3) constexpr long long int abs (long long int n); // 4) constexpr long labs( long n ); // 5) constexpr long long llabs( long long n ); // 6) constexpr /* floating-point-type */ abs( /* floating-point-type */ n ); Defined in <cmath> // 7) constexpr /* floating-point-type */ fabs ( /* floating-point-type */ n ); // 8) constexpr float fabsf( float n ); // 9) constexpr long double fabsl( long double n ); Defined in <cinttypes> // 10) std::intmax_t abs( std::intmax_t n ); // 11) std::intmax_t imaxabs( std::intmax_t n ); Additional Overloads ·
🌐
GitHub
github.com › elbeno › constexpr
GitHub - elbeno/constexpr: Experiments with constexpr · GitHub
Everything (with the exception of noted functions) is written in C++11 constexpr style for maximum compatibility. All functions are within the cx namespace. This code is distributed under the MIT license. See LICENSE for details. ... String encryption uses std::make_index_sequence therefore requires C++14.
Starred by 248 users
Forked by 26 users
Languages   C++ 97.8% | Python 1.1% | CMake 1.1%
🌐
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.
🌐
Marzer
marzer.github.io › muu › modules.html
muu Miscellaneous useful utilities for C++
module Hashing Utilities for generating (non-cryptographic) hashes. module Iterators Utilities for working with iterators. module Math Math functions and types. module abs() Constexpr-friendly alternatives to std::abs. module acos() Constexpr-friendly alternatives to std::acos.
🌐
Cppreference
en.cppreference.com › w › cpp › numeric › math › fabs.html
std::abs(float), std::fabs, std::fabsf, std::fabsl - cppreference.com
March 14, 2025 - 1-4) Computes the absolute value of the floating-point value num. The library provides overloads of std::abs and std::fabs for all cv-unqualified floating-point types as the type of the parameter num.(since C++23)
🌐
Google Groups
groups.google.com › a › isocpp.org › g › std-discussion › c › rwXFfo-_Rys
std::abs() on std::chrono::duration
Hi, I noticed that it seems the C++11 standard doesn't require std::abs() to be defined for std::chrono::duration. If I understand correctly, std::abs() is defined on integers (declared in header file <cstdlib>), floats (<cmath>), complex (<complex>), and valarray (<valarray>), but not on std::chrono::duration.
🌐
Open-std
open-std.org › jtc1 › sc22 › wg21 › docs › papers › 2016 › p0415r0.html
Constexpr for std::complex
August 10, 2016 - Operations other than +,-,*,/,norm,conj use a lot of functions from <cmath>. It's unreasonable to mark them with constexpr right now. abs(const complex<T>&) seems highly usable however it requires either sqrt or hypot to be constexpr.