Follow

C++ rage 

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 ?

C++ rage 

@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.)

C++ rage 

@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

C++ rage 

@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

C++ rage 

@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...

C++ rage 

@namark @shivoa no, it's the opposite

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

1/2

C++ rage 

@namark @shivoa

2. Performance

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

2/2

C++ rage 

@norado @shivoa But do you want to use any libraries(or your own utility code) doing any of that? Be that basic utility functions or complex algorithms, they either need to be able to run in both contexts, or come in two identical copies, one for compile time and one for runtime.

C++ rage 

@norado @shivoa
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.

C++ rage 

@namark @shivoa again I understand that I could do those Things

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

C++ rage 

@norado @shivoa My point was that it's not that hard and can be done at callsite:
class c {
constepxr static auto t = make_table();
};

or

void f(){
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.

C++ rage 

@namark @shivoa I think you might underestimate how easy it is to have a complex callsite and as there are no guarantees you still have to look at the asm to be sure !!

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

C++ rage 

@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 (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.

C++ rage 

@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 :)

C++ rage 

@norado @shivoa If you use constexpr the way it's intended, it's not that hard to get it right. consteval will help communicate your intent in code, but without constexpr, everyone writing consteval functions will be back to stone age.

C++ rage 

@namark @shivoa I am not against constexpr necessarily (though I don't think it is that helpful in general), but it shouldn't be the default and most things I've read seem to assume it is consteval

C++ rage 

@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 =)

C++ rage 

@namark @shivoa a bit, but this also gave me an avenue to let it out which always helps :)

C++ rage 

@namark @shivoa I don't really see much identical code I would want to run in both contexts and I don't think that will be a common case

Sign in to participate in the conversation
Gamedev Mastodon

Mastodon server focused on game development and related topics.