Is it a conforming compiler extension to treat non-constexpr standard library functions as constexpr?

TL;DR

In C++14 this is explicitly not allowed, although in 2011 it appeared like this case would be explicitly allowed. It is unclear if for C++11 this fell under the as-if rule, I don’t believe it does since it alters observable behavior but that point was not clarified in the issue I reference below.

Details

The answer to this question has shifted with the evolving status of LWG issue 2013 which opens with:

Suppose that a particular function is not tagged as constexpr in the
standard, but that, in some particular implementation, it is possible
to write it within the constexpr constraints. If an implementer tags
such a function as constexpr, is that a violation of the standard or
is it a conforming extension?

In C++11 it was unclear if the as-if rule permitted this but the orignal proposal would have explicitly allowed it once it was accepted and we can see below in the gcc bug report I reference, this was the assumption made by the gcc team.

The consensus to allow this shifted in 2012 and the proposal changed and in C++14 this is a non-conforming extension. This is reflected in the draft C++14 standard section 17.6.5.6 [constexpr.functions] which says:

[…]An implementation shall not declare any standard library function
signature as constexpr except for those where it is explicitly
required.[..]

and although a strict reading of this seems to leave some wiggle room for treating a builtin implicitly as if it were a constexpr we can see from the following quote in the issue that the intention was to prevent divergence in implementations since identical code could produce different behavior when using SFINAE (emphasis mine):

Some concern expressed when presented to full committee for the vote
to WP status that this issue had been resolved without sufficient
thought of the consequences for diverging library implementations, as
users may use SFINAE to observe different behavior from otherwise
identical code
.

We can see from the gcc bug report [C++0x] sinh vs asinh vs constexpr that the team relied on the earlier proposed resolution of LWG 2013 which says:

[…]Additionally, an implementation may declare any function to be
constexpr if that function’s definition satisfies the necessary
constraints[…]

when deciding whether this change for the math functions was allowed in strict conformance mode.

As far as I can tell this would become conforming if this we received a warning in strict conformance mode i.e. using -std=c++11 -pedantic or if it was disabled in this mode.

Note, I added a comment to the bug report explaining that the resolution changed since this issue was originally addressed.

Jonathan Wakely pointed out in another question a more recent discussion and it seems likely the gcc bug report will be reopened to address this conformance issue.

What about intrinsics

Compiler intrinsics are not covered by the standard and so as far as I can tell they should be exempt from this rule, so using:

static constexpr double a = __builtin_cos(3.);

should be allowed. This question came up in the bug report and opinion of Daniel Krügler was:

[…]Library functions and other intrinsics can probably be considered as
exceptions, because they are not required to be “explainable” by
normal language rules.

Leave a Comment