Live data from Hacker News

Reflection for C++26

isocpp.org

121–130 of 214 posts

Re: Reflection for C++26

#121
post #58

Earlier quoted context omitted.

I always thought it’s good practice in C/C++ to have only one translation unit in release builds e.g. SQLite amalgamations, instead of relying on LTO. It also speeds up compilation because it isn’t recompiling the same header files over and over again.

It's a cute idea but just not scalable. It doesn't speed up compilation because separate translation units can be compiled independently and cached.

Do things that don’t scale :)

Obviously it’s not suitable for dev builds, I don’t think anyone uses it for that. For release builds you would want to clear caches anyway.

Re: Reflection for C++26

#122

Earlier quoted context omitted.

This is terrible. You can't just do Enum::Member.str or something?

What are you talking about? At runtime, an enum value is just an integer. You need to look up the enum case that corresponds to your integer in order to convert it to a string. Which is precisely what the code above is doing.

Yeah, C++ enums are just numbers that are really good at pretending to be types. And for that reason they're not actually objects that contain things like their name. And they probably shouldn't, in the vast majority of cases it would be an utter waste of space to store the names of enum members along with them. So you have compile-time reflection for those instead. And yeah, you could implement some kind of thing pretending to be a member but actually being a reflection thing but that's both horrifying and limited so C++ takes the reasonable approach of just adding general reflection in instead.

Re: Reflection for C++26

#123
post #84

Earlier quoted context omitted.

Thankfully it is so easy to quickly import libraries into C++...

It actually is, for anyone using Conan or vcpkg.

So our team switched to vcpkg recently and, while it has improved certain parts of our dependency process, it has also made other parts more complex. Notably when something suddenly goes wrong it is far more complex to figure out what actually happened (Though to be fair a lot of these issues also come from combining vcpkg with cmake). This led to most of my team revolting against vcpkg and now it looks like we might go back to just vendoring our libraries again.

I suppose I just yearn for an all-in-one build system + package manager like exists in Rust or Go. Once you've seen what can be possible when these things are integrated from the ground up it sort of ruins your C++ build experience!

Re: Reflection for C++26

#124
post #116

Earlier quoted context omitted.

shared_ptr isn't the only smart pointer and definitely shouldn't be used for everything. The default should be unique_ptr which is simple to reason about and a huge improvement over only having raw pointers that may or may not be owning what they point to.

unique_ptr is often too restricted. If you have a simple tree with unique_ptr, already the back edges need to be raw pointers to avoid cycles. If you add an iterator, the iterator needs internal pointers to the nodes, so by definition the node pointers are not unique. Again, raw pointers are better. I have never seen a complex data structure where unique_ptr is really used.

Yes, smart pointers don't mean you can entirely stop thinking about ownership and lifetimes but they let you express that ownership in an explicit way with some compiler-enforced protections against mistakes.

> I have never seen a complex data structure where unique_ptr is really used.

What's a "complex" data structure? Anyway, I'd expect to see unique_ptr more in user code rather than in library implementations of data structures where where relatively minor concerns might warrant an ad-hoc implementation even if you could use unique_ptr. In many cases it's probably just that the implementations precede the standardized smart pointers.

Re: Reflection for C++26

#125

I haven't touched C++ since undergrad. Neither have I written any Qt code. But from memory, doesn't Qt's moc implement some of this stuff because it wasn't available in C++? Could this replace moc?

Qt has straight-up dynamic reflection. You can get pointers to functions from strings, and such. This is just static reflections (which is still very useful!), so it's not a complete replacement. Even if it was, I would Qt would replace its build system.

Static reflection makes it much easier to build dynamic reflection though, especially without meta-compilers and excessive macro use.

Re: Reflection for C++26

#126

I haven't touched C++ since undergrad. Neither have I written any Qt code. But from memory, doesn't Qt's moc implement some of this stuff because it wasn't available in C++? Could this replace moc?

moc can be replaced without reflection: https://woboq.com/blog/verdigris-qt-without-moc.html

Using ugly macro hacks, yes.

Re: Reflection for C++26

#127
post #93

Earlier quoted context omitted.

I always thought it’s good practice in C/C++ to have only one translation unit in release builds e.g. SQLite amalgamations, instead of relying on LTO. It also speeds up compilation because it isn’t recompiling the same header files over and over again.

That's called a "unity build", build systems such as cmake support it. It has its pros and cons.

And while it helps with compile time (especially with mediocre compilers like MSVC where a large time is spent in the front-end), it doesn't help with stripping unneeded code/data compared to LTO.

Re: Reflection for C++26

#128
post #58

Earlier quoted context omitted.

I always thought it’s good practice in C/C++ to have only one translation unit in release builds e.g. SQLite amalgamations, instead of relying on LTO. It also speeds up compilation because it isn’t recompiling the same header files over and over again.

It's a cute idea but just not scalable. It doesn't speed up compilation because separate translation units can be compiled independently and cached.

It does significantly speed up clean builds in many cases, to the point that those clean builds can even be faster than many "incremental" builds in some cases.

Re: Reflection for C++26

#129
post #57

Earlier quoted context omitted.

You can't have two functions that differ in just the return type in C++

You can sort of do it so long as the return type is a template parameter. template T my_construct() { T result; return result; }

That's not polymorphism as that template parameter won't be deduced in any context and you will always have to explicitly instantiate the template.

Re: Reflection for C++26

#130

Earlier quoted context omitted.

This is the thing that's driving me away from C++ very quickly. A big part of our code base is code that handles this, and it either has to be in a DSL and constantly recompiled or we have to make a bunch of boilerplate. It's a huge problem for the language not to be able to do this.

Example of serializing a C++ object to JSON with reflection: template std::string to_json(const T& obj) { std::ostringstream oss; constexpr auto type_info = reflect(T); if constexpr (type_info.is_fundamental()) { // Fundamental types (int, float, etc.) if constexpr (std::is_same_v ) { oss ) { oss ) { oss >) { // Arrays and vectors oss >) { // Maps oss hobbies; std::map scores; }; int main() { Person person { "John Do…

That is cool. Would it be possibly implement something like Golangs %v and %T printf formatters?
Post reply on HN