STL
STL copied to clipboard
P0533R9 `constexpr` For `<cmath>` And `<cstdlib>`
P0533R9 constexpr For <cmath> And <cstdlib>
LWG-3834 Missing constexpr for std::intmax_t math functions in <cinttypes>
Feature-test macro:
#define __cpp_lib_constexpr_cmath 202202L
We need to investigate this sooner rather than later to determine exactly how we're going to make UCRT functions constexpr. I suspect we'll have to teach the compiler(s) to recognize e.g. ::ldexp and std::ldexp, at least when they appear in constant expressions, and constant-fold them. This is going to involve a lot of joint work and communication with our compiler teams.
I think it is implementable without compiler support. You have constexpr bit_cast, you know the representation of floats, you do the math.
Compiler support looks better though. Be sure to have it in clang-cl either.
I don't think compiler support is essentially needed (but may be nice to have). We can ask UCRT not to declare these functions, but to provide some equivalent functions with different names (e.g. __cstd_fabs, which may be suitable to be called at runtime) in C++23 mode. The definitions of existing UCRT functions can be unchanged.
Perhaps we can provide "some equivalent functions with different names" in MSVC STL only, by [[__gnu__::__alias__("...")]] (for clang) or #pragma comment(linker, "/alternatename:...") (for MSVC, see this).
For example, we might be able to change our ldexp to have "C++" language linkage in C++23 mode, and hence it will be mangled and won't conflict to the ldexp in UCRT (which has "C" language linkage). And it may call __cstd_ldexp at runtime, where __cstd_ldexp is an alias for the ldexp in UCRT.
Edit: The alternatename trick is unnecessary. I guess we can just sweep UCRT functions in a non-global internal namespace in C++ modes.
a few initial thoughts from LLVM discord: https://discord.com/channels/636084430946959380/636732781086638081/942850475752062989
@ldionne wrote:
Oh! Of course.
// inside <math.h>
int abs(int);
// inside <cmath>
namespace std {
constexpr int abs(int) {...}
}
// user code:
using namespace std;
abs(1); // which one is meant?
Okay.. yeah this is messed up
Geez I don't know how to solve that problem, actually
Well the only way would be for the C standard library version to be constexpr
Either by means of them defining it as such, or the compiler doing some extra nasty magic when it sees these names
However, asking the C library folks to implement something based on something like std::is_constant_evaluated() is not a happy story
I've contacted the compiler team about getting support for this.
We should ask the compiler team to consider implementing #3789 at the same time to save work.
The attribute [[msvc::constexpr]] allows "extended constexpr" in C++20 such as calling placement new from within a constexpr function for std::construct_at, could that attribute be extended to allow using these blessed functions in a constant expression?
Seems like the least painful approach in terms of existing blessed constexpr and without needing to reimplement every function manually again
Seems like the least painful approach in terms of existing blessed constexpr and without needing to reimplement every function manually again
I think the crux is the UCRT headers (mainly <math.h> in the case of this issue) - they seem somehow "freezed", so it's unclear whether we can even add attributes to declarations in them. As a result, compiler frontends seemingly need work around this when such a function calls is encountered in constant evaluation.
We need to investigate this sooner rather than later to determine exactly how we're going to make UCRT functions
constexpr. I suspect we'll have to teach the compiler(s) to recognize e.g.::ldexpandstd::ldexp, at least when they appear in constant expressions, and constant-fold them. This is going to involve a lot of joint work and communication with our compiler teams.
Ah, it seems that no progress seem was made since then. If MS had allowed us to touch related UCRT headers or reorganize them like <stdatomic.h>, we would probably have implemented the whole library workaround before 2024.
(Also, the alternatename trick does't seem unnecessary. Probably another internal namespace suffices.)
We're having a meeting on 2025-05-07 with the compiler and UCRT teams to figure out the plan here.
We're having a meeting on 2025-05-07 with the compiler and UCRT teams to figure out the plan here.
Is there any news to share?
Not yet, the compiler team is still looking into this before deciding on a course of action. A major concern is how to address accuracy issues (i.e. should the compiler prioritize mathematically-correct results, or UCRT bug-compatibility).
(i.e. should the compiler prioritize mathematically-correct results, or UCRT bug-compatibility).
For the sanity of our future selves, please advocate for prioritizing "correct results". Old UCRT versions will fade away over time, but intentionally buggy core math functions will keep biting people ~forever
That's what I'm advocating for whenever the compiler team asks me.