I just learned that a constexpr function can be evaluated at runtime instead of compile time without emiting any diagnostic...
Why is everything in this language fucked to such an extent ?
@norado Can you use it in a macro that causes a compile issue when not evaluated at compile time (eg static_assert with it) to avoid the compiler getting clever and swapping out a run-time equivalent when you want a compile-time constant? (I'm not a C++ expert, ignore if this is a silly Q.)
@shivoa you can use various kinds of template magic that tries to use the function as a template argument that fails when it can't be evaluated at compiletime, but it's really, really gross
For C++ 20 they added 'consteval' as keyword alternative that guarantees that the expression has to be evaluated at compiletime and errors if not
Still nasty that no tutorial or introduction I could find really talks about it, so tons of people have slow code paths they don't know about
@shivoa it's just another of these things where C++ solves a problem you really want solved, but does so in the worst way possible
@norado @shivoa but... but that's the best thing about constexpr code... it works in both contexts, so you don't have to duplicate your entire world just to move something from compile time to run time and vice versa... and in my experience it's usually quite easy to tell which context you are in, or force the context...
There are imo 2 reason for wanting something to happen at compiletime instead of runtime.
1. You want to setup something or config something -> afaik constexpr isn't great at that at the moment because it has tons of restrictions for stuff that can run. But you obviously want that to always happen at compiletime
Performance is only really helpful if it is 100% reliable (!!)
If I write a constexpr it could run at runtime, so I now have to look at the asm of all Instances the function is called to find out if it happened at compiletime or will happen at runtime.
That is useless
It also will have a build time overhead and often generates worse code at runtime than without constexpr
This adds more work and restrictions on the code without reliable advantage
To try address the specific points:
1. Setup/Config - depends on what you're setting up, if it's a constexpr variable the setup code is guaranteed to run at compile time.
2. Performance - might be my lack of experience, but I can't see how constexpr can help performance other than doing the same setup/config(pre-computing lookup tables, constants), in which case again you can store the data in const/constexpr variables.
The point is that the compiler does not guarantee it, so the only thing you build in with that is the ability for people to make mistakes that will be very hard to detect
As an example for performance reasons are big pre-calculations, generating lookup tables etc.
With that stuff you need to be 100% sure that it does not run at compiletime and having to manually check is nuts
constepxr auto t = make_table();
both guarantee compile time.
consteval would help make sure that make_table is never used in runtime context, but for functions like lerp or gauss_elimination, that it might be using internally, contexpr makes more sense.
consteval is nice, but constexpr is essential when you look at the big picture.
Even if you declare everything right the compiler still could do it at runtime, and when you look up the rules, they are way more complicated. look at the 'core constant expression' rules for when something can't be run at compile time
Also the runtime constexpr version is sometimes slower than without constexpr
@norado @shivoa looked it up and found some discussions referring to the standard, but at that level there are no concepts of compile time or run time, since the language might not even be compiled (https://github.com/root-project/cling)
Still that doesn't mean that compilers are free to be insane. If you find a case where your compiler(with optimizations on) generates runtime code for the call in those two cases, then a bug report is due.
@norado @shivoa I can't really see how callsite can get more complicated for a function that needs to be executed at compile time. If you are passing it around to be executed in unknown context, it's unlikely that it even can be done at compile time, unless the whole call tree is constexpr, in which case you can use the same trick to enforce compile time or get an error. And when you get that error, my guess is that in most of complicated cases the only way out is to do it in runtime :)
@norado @shivoa I also haven't come across any good introductory material, other than some longer talks, which are hard to find or sort trough. I agree that consteval might be a better starting point for that purpose, before introducing the constexpr, which is more complicated.
Hope I quenched at least some of the rage on constepxr =)
Mastodon server focused on game development and related topics.