MSVC 2015 cannot compile constexpr atan - c++

I have used Mingw-w64 compiler in my project. Now I am compiling the project with MSVC2015. The following line gives an error:
constexpr double pi = 4*std::atan(1);
error:
error: C2131: expression did not evaluate to a constant
However it compiled in mingw without any problems.

MSVC is right in this case, from [constexpr.functions]p1
This document explicitly requires that certain standard library functions are constexpr. An implementation shall not declare any standard library function signature as constexpr except for those where it is explicitly required.
As you can see from the last sentence that I highlighted, an implementation is not allowed to declare a function constexpr if the standard doesn't say so.
Now does the standard say that atan is constexpr? No, as can be seen from the signature in [c.math]:
float atan(float x); // see [library.c]
double atan(double x);

Related

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

gcc compiles the following code without warning:
#include <cmath>
struct foo {
static constexpr double a = std::cos(3.);
static constexpr double c = std::exp(3.);
static constexpr double d = std::log(3.);
static constexpr double e1 = std::asin(1.);
static constexpr double h = std::sqrt(.1);
static constexpr double p = std::pow(1.3,-0.75);
};
int main()
{
}
None of the standard library functions used above are constexpr functions, we are allowed to use them where a constant expression is required from both the draft C++11 standard and draft C++14 standard section 7.1.5 [dcl.constexpr]:
[...]If it is initialized by a constructor call, that call shall be a
constant expression (5.19). Otherwise, or if a constexpr specifier is
used in a reference declaration, every full expression that appears in
its initializer shall be a constant expression.[...]
Even when using -std=c++14 -pedantic or -std=c++11 -pedantic no warnings are generated (see it live). Using -fno-builtin produces errors (see it live) which indicates that the builtin version of these standard library functions are being treated as if they where constexpr
While clang does not allow the code with any combination of flags I have tried.
So this is a gcc extension to treat at least some builtin functions as if they were constexpr functions even though the standard does not explicitly require them to be. I would have expected to at least receive a warning in strict conformance mode, is this a conforming extension?
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.

Why isn't abs constexpr?

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?
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 declared
constexpr if 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, 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.
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.
It is constexpr since C++23
long abs( long n ); (2) (constexpr since C++23)
https://en.cppreference.com/w/cpp/numeric/math/abs

const type to const alias in C++11

I am using Clang included in Xcode 4.6.2 (4H1003).
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Currently my compiler doesn't make a compile error for this code.
using AA = int const;
static AA const aa = 0;
Because I am not familiar with accurate C++11 specs, I can't know what is correct behavior.
Error for double const keyword.
const on using is not allowed.
This is some special case.
This is compiler bug.
What is expected behavior by standard?
This was already allowed back with C++98 - cv-qualifiers can be introduced multiple times through typedef names and template parameters - they're simply collapsed. If this wasn't allowed, generic code would have a lot of problems. The same thing happens for references too.
§7.1.6.1 [dcl.type.cv] p1:
There are two cv-qualifiers, const and volatile. [...]
Redundant cv-qualifications are ignored. [ Note: For example, these could be introduced by typedefs.—end note ]

implicit constexpr?

Can C++11 compilers (and do they) notice that a function is a constexpr and treat them as such even if they are not declared to be constexpr?
I was demonstrating the use of constexpr to someone using the example straight from the Wikipedia:
int get_five() {return 5;}
int some_value[get_five() + 7]; // Create an array of 12 integers. Ill-formed C++
To my surprise the compiler was OK with it. So, I further changed get_five( ) to take a few int parameters, multiply them and return the result while still not being explicitly declared to be constexpr. The compiler was OK with that as well. It seems that if the compiler can do this there isn't much point to having the restrictions that are required in order to explicitly declare something constexpr.
On a properly-functioning C++11 compiler, your code would be rejected.
Based on its being accepted, you're almost certainly using gcc (or something that closely emulates its bugs). gcc [depending somewhat on flags] can accept array sizes that aren't constant by any measure (e.g., depend on run-time input from the user) because they support an analog of C99 variable-length arrays in C++.
GCC, as of GCC 12, supports the -fimplicit-constexpr command-line toggle which enables exactly that, for methods marked as inline.
Changelog: https://gcc.gnu.org/gcc-12/changes.html
Patch with some rationale and discussion: https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=87c2080b
A compiler can detect whether or not a function could have been declared with constexpr even when they haven't, for optimization purposes (i.e. computing the result of a function at compile-time). Compilers did that prior to C++11.
But for use in places that requires constant expressions, such as template parameters of integral type, it is against the standard to allow calls to functions that are not declared with the constexpr keyword.

void, VOID, C and C++

I have the following code:
typedef void VOID;
int f(void);
int g(VOID);
which compiles just fine in C (using gcc 4.3.2 on Fedora 10). The same code compiled as C++ gives me the following error:
void.c:3: error: ‘<anonymous>’ has incomplete type
void.c:3: error: invalid use of ‘VOID’
Now, this is something in external library and I would like the owner to fix that problem. So I have a question - does C++ standard forbids this construct? Could you give me a pointer/citation? The only thing I can recall is that function declaration with (void) to signal empty parameter list is deprecated in C++, but I don't understand why typedefed VOID does not work.
Yes, as far as i know the second declaration is invalid in C++ and C89, but it is valid in C99.
From The C99 draft, TC2 (6.7.5.3/10):
The special case of an unnamed parameter of type void as the only item in the list
specifies that the function has no parameters.
It's explicitly talking about the type "void", not the keyword.
From The C++ Standard, 8.3.5/2:
If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.
That it means the actual keyword with "void", and not the general type "void" can also be seen from one of the cases where template argument deduction fails (14.8.2/2):
Attempting to create a function type in which a parameter has a type of void.
It's put clear by others, notable in one core language issue report here and some GCC bugreports linked to by other answers.
To recap, your GCC is right but earlier GCC versions were wrong. Thus that code might have been successfully compiled with it earlier. You should fix your code, so that it uses "void" for both functions, then it will compile also with other compilers (comeau also rejects the second declaration with that "VOID").
gcc bugs. Edit: since it wasn't clear enough, what I meant was gcc 4.3.2 was compiling it due to bugs. See #32364 and #9278.
I just put your code in a .cpp file, and it compiled with no problems in VS2005, SUSE, Redhat, and Solaris, so I guess your specific gcc version does not approve of this.
Gal