Live data from Hacker News

Cost of enum-to-string: C++26 reflection vs. the old ways

vittorioromeo.com

91–100 of 189 posts

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#91
post #88
post #2

Oof, that first example (the idiomatic C++26 way) looks so foreign if you're mostly used to C++11.

I wish I understood the reason for the `std::define_static_array`... Why can't `std::meta::enumerators_of` just return something that can be iterated through????

It is kind of weird at first but the reason is that `std::vector` requires heap allocation and transient allocations are not allowed in `constexpr` contexts. The purpose of `std::define_static_array` is to promote the storage of the vector to static storage to eliminate the transient allocation issue, and so that the `template for` can work properly with it.

See wg21.link/P3491

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#92
post #88

Earlier quoted context omitted.

I wish I understood the reason for the `std::define_static_array`... Why can't `std::meta::enumerators_of` just return something that can be iterated through????

It is kind of weird at first but the reason is that `std::vector` requires heap allocation and transient allocations are not allowed in `constexpr` contexts. The purpose of `std::define_static_array` is to promote the storage of the vector to static storage to eliminate the transient allocation issue, and so that the `template for` can work properly with it. See wg21.link/P3491

Is there a reason why `std::meta::enumerators_of`, a reflection feature that's surely almost exclusively going to be used in constexpr contexts, returns a value which doesn't work in constexpr contexts?

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#93
post #60

Earlier quoted context omitted.

...so what? It's just a header you have to #include.

By that logic why would anything have to be standardised?

By your logic we shouldn't ever use external libraries.

PFR has given us reflection since C++14.

I also don't think the Standard Library is particularly well-defined nor well-implemented, as demonstrated by the atrocious compilation times.

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#94
post #81

Earlier quoted context omitted.

Are X macros awkward? I find them very straightforward and clear.

The implementation doesn't look too bad, but the usage is terrible: #define E_LIST(X) \ X(V0) X(V1) X(V2) X(V3) DEFINE_ENUM(E, E_LIST) That's not how I want to declare my enums...

To be honest there are ways to make that much nicer. I believe that if you use recursive macros using the VA_OPT feature, you should be able to provide enumerators directly to define enum as a list.

The underlying machinery implementation is going to be much uglier and complex, though.

See https://www.scs.stanford.edu/~dm/blog/va-opt.html

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#95

> The header is the cost. Not the reflection. The reflection algorithm is fast – asymptotically ~0.07 ms per enumerator, essentially the same as the hand-rolled switch in the X-macro version (~0.06 ms). What makes reflection look expensive is : just including it costs ~155 ms per TU over the baseline. So speaking of old ways, I'm not a C++ dev, but a while ago saw someone comment that they still organize their C++ pr…

This cost is not significant nowadays, it's the frontend/parsing time. You can also use `#pragma once` which works everywhere, is nicer, and technically needs less work by the compiler, but compilers have optimized for include guards since a long time ago. Some random measurements I found: https://github.com/Return-To-The-Roots/s25client/issues/1073

Yes, I've heard that before, but comments like this one in your linked issue still make me wonder:

> at least for gcc and Visual Studio using #pragma once has a significant impact. The fact is, the compiler does not need to continue parsing the whole file when reaching a #pragma once. otherwise the compiler always needs to do it even if the include guard afterwards will avoid double processing of the content afterwards.

As written the explanation for these optimizationst suggest that both "pragma once" and include guard optimization still requires opening and closing the file each time an include is encountered, even if you bail after parsing the first line. Is that overhead zero? Or are the optimizations explained poorly and is repeatedly opening/closing the file also avoided?

Either way, do you know what causes the slowdown as a result of including ?

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#96

Earlier quoted context omitted.

This works for extreme needs. But you're probably not doing s ton of metaprogramming all the time like you should be, and would with a language that allows it. The lack of metaprogramming is also why C is so slow compared to C++

C is not slow compared to C++, that is a strange myth.

In practice, C means you end up with generic data structures with pointers to what they contain, rather than being inline.

You do see a lot of macro use to deal with this, but that is just primitive, non-typesafe metaprogramming, and it gets unwieldy enough that in practice, you see people add an extra pointer. This is why it gets slower.

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#98

Earlier quoted context omitted.

C is not slow compared to C++, that is a strange myth.

In practice, C means you end up with generic data structures with pointers to what they contain, rather than being inline. You do see a lot of macro use to deal with this, but that is just primitive, non-typesafe metaprogramming, and it gets unwieldy enough that in practice, you see people add an extra pointer. This is why it gets slower.

If you need callbacks and generics, you're not writing performance code.

99% of code in the wild is comically inefficient and is doing the wrong thing, using way too generic data structures and algorithms for very concrete problems. C++ templates may be one way to make comically slow code faster by spending a lot of compile time. But it's often much quicker to just write straightforward concrete code that the compiler can easily optimize.

IMO C++ makes for slow programs for the sole fact that it compiles so slow (if you use its modern features), so you have much less time to actually iterate and improve.

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#99
post #81

Earlier quoted context omitted.

The downside is, of course, that it's ugly and very awkward to use. That's the essence of C++: you're basically trading ergonomics for compile times.

Are X macros awkward? I find them very straightforward and clear.

They are gross but... effective so shrug

Re: Cost of enum-to-string: C++26 reflection vs. the old ways

#100
post #57

Never quite understood why people are so obsessed with meta programming capabilities in a language, be it templates, comptime, macros, whatever. I program mostly in C, if I need 'meta' programming I just write another C program that processes C source code (I've written a simple C parser), then in my build script I build in two stages, build meta program, run it, build rest of program. Simple, effective, debuggable (…

Why would I write a parser that almost-but-not-quite matches the compiler's own parser, when I could just use the compiler's parser directly? I don't want to write a parser, and I especially don't want to debug weird corner cases where my implementation diverges somehow. I just want to write some code that goes like, for each field in T, do X. C++ metaprogramming is bad, but the problem there is the C++ part, not the…

Cause its dead simple. Shell out, run a quick sed or something, then compile it in. It is quite amazing what 'magic meta' stuff you can do with that shit. Meanwhile 10 years in we are finally getting reflection.....
Post reply on HN