26

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?

Shoe
  • 74,840
  • 36
  • 166
  • 272
  • For historical and compatibility reasons – Basile Starynkevitch Dec 30 '14 at 16:06
  • 5
    @BasileStarynkevitch: Can you explain one of these compatibility reasons? – Lightness Races in Orbit Dec 30 '14 at 16:14
  • 5
    @BasileStarynkevitch I don't buy that. Given a compatible compiler, a constexpr piece of code will work the same as it used, i.e. when passed in non-constexpr values it will return a non-constexpr. If it preferable to compatible to not make these functions constexpr (or alteast with constexpr overloads) then it would be preferable to not include move instructors for vector. Being that this uses namespaces (so is not C) and is a header provided only in C++11, I would like to see constexpr overlaods. – IdeaHat Dec 30 '14 at 16:16
  • 7
    `abs` is a C99 function. And C99 has no idea of `constexpr` – Basile Starynkevitch Dec 30 '14 at 16:32
  • 19
    There are **a lot** of functions that could be constexpr and are not *(yet)*. More functions will slowly become constexpr with each revision of the standard. Feel free to participate in that process (instructions on isocpp.org). – Marc Glisse Dec 30 '14 at 16:40
  • 3
    `abs` is not `constexpr` because the standard decided so. I think this is the wrong place to ask why. What I can say is that if you *really* need a `constexpr abs`, write your own one. You can't go wrong. – edmz Dec 30 '14 at 17:02
  • Gotta keep those cross-compiled one's complement machines going :) – Hans Passant Dec 30 '14 at 17:03
  • 1
    @LightnessRacesinOrbit well Howard Hinnant gave an example [here](http://clang-developers.42468.n3.nabble.com/libcxx-RFC-C-14-and-beyond-td4031862.html) showing how adding constexpr to old code could change behavior. So I would assume caution is the main reason, it does not seem like there is a pressing need and potentially breaking old code is a good reason to take your time. – Shafik Yaghmour Dec 30 '14 at 19:05
  • 1
    @BasileStarynkevitch: An `abs` taking `std::intmax_t` is clearly not from C99. – Lightness Races in Orbit Dec 30 '14 at 22:33
  • 1
    @ShafikYaghmour: That example is pretty contrived. – Lightness Races in Orbit Dec 30 '14 at 22:34
  • 2
    Mirrored at http://cpc110.blogspot.co.uk/2014/12/why-isn-abs-constexpr.html without attribution. – Lightness Races in Orbit Jan 03 '15 at 17:29
  • @ShafikYaghmour that kind of example even applies to adding `void std::vector::eat_pie() const {}` -- with SFINAE, almost any change accessible in an immediate context can be breaking through obtuse "detect if the change was made" logic. – Yakk - Adam Nevraumont Mar 13 '15 at 19:55
  • @Yakk well as a additional note this is kind of logic used when deciding whether implementations could add constexpr to standard library function, see the [details here](http://stackoverflow.com/a/27744080/1708801). – Shafik Yaghmour Mar 13 '15 at 20:04

4 Answers4

14

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.

Edward
  • 6,964
  • 2
  • 29
  • 55
  • For more details re [gcc and match functions treated as constexpr](http://stackoverflow.com/q/27744079/1708801). gcc allowed this since they thought this was going to be allowed but it was not. – Shafik Yaghmour Nov 13 '15 at 20:29
  • 1
    In [Proposal P0533](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0533r1.pdf), it is stated that GCC has taken the lead as the "State of the Art" in defining `constexpr` functions in ``. – leek Nov 22 '18 at 23:04
9

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.

leek
  • 861
  • 8
  • 12
2

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.

Peter
  • 35,646
  • 4
  • 32
  • 74
0

It is constexpr since C++23

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

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

Mikhail
  • 7,749
  • 11
  • 62
  • 136