And then there are templates.Templates in C++ are nothing likegenerics in other languages. Everytemplate instantiation creates anew type. std::vector is a completely separate class fromstd::vector. That adds up toa lot of different types in a entireprogram. What should our reflectionsee? The template std::vector? Buthow can it, since that's asource-code construct, which has nomeaning at runtime? It'd have to seethe separate classesstd::vector andstd::vector. Andstd::vector::iterator andstd::vector::iterator, samefor const_iterator and so on. Andonce you step into templatemetaprogramming, you quickly end upinstantiating hundreds of templates,all of which get inlined and removedagain by the compiler. They have nomeaning, except as part of acompile-time metaprogram. Should allthese hundreds of classes be visibleto reflection? They'd have to,because otherwise our reflectionwould be useless, if it doesn't even guarantee that the classes I defined will actually be there. And a side problem is that the template class doesn't exist until it is instantiated. Imagine a program which uses std::vector. Should our reflection system be able to see std::vector::iterator? On one hand, you'd certainly expect so. It's an important class, and it's defined in terms of std::vector, which does exist in the metadata. On the other hand, if the program never actually uses this iterator class template, its type will never have been instantiated, and so the compiler won't have generated the class in the first place. And it's too late to create it at runtime, since it requires access to the source code.
cdleary:Yes, debug symbols do something similar, in that they store metadata about the types used in the executable. But they also suffer from the problems I described. If you've ever tried debugging a release build, you'll know what I mean. There are large logical gaps where you created a class in the source code, which has gotten inlined away in the final code. If you were to use reflection for anything useful, you'd need it to be more reliable and consistent. As it is, types would be vanishing and disappearing almost every time you compile. You change a tiny little detail, and the compiler decides to change which types get inlined and which ones don't, as a response. How do you extract anything useful from that, when you're not even guaranteed that the most relevant types will be represented in your metadata? The type you were looking for may have been there in the last build, but now it's gone. And tomorrow, someone will check in a small innocent change to a small innocent function, which makes the type just big enough that it won't get completely inlined, so it'll be back again. That's still useful for debug symbols, but not much more than that. I'd hate trying to generate serialization code for a class under those terms.
DOWNLOAD ✫ https://t.co/Rssg65QimN
Evan Teran: Of course these issues could be resolved. But that falls back to my point #1. It'd take a lot of work, and the C++ committee has plenty of things they feel is more important. Is the benefit of getting some limited reflection (and it would be limited) in C++ really big enough to justify focusing on that at the expense of other features? Is there really a huge benefit in adding features the core language which can already (mostly) be done through libraries and preprocessors like QT's? Perhaps, but the need is a lot less urgent than if such libraries didn't exist.For your specific suggestions though, I believe disallowing it on templates would make it completely useless. You'd be unable to use reflection on the standard library, for example. What kind of reflection wouldn't let you see a std::vector? Templates are a huge part of C++. A feature that doesn't work on templates is basically useless.
But you're right, some form of reflection could be implemented. But it'd be a major change in the language. As it is now, types are exclusively a compile-time construct. They exist for the benefit of the compiler, and nothing else. Once the code has been compiled, there are no classes. If you stretch yourself, you could argue that functions still exist, but really, all there is is a bunch of jump assembler instructions, and a lot of stack push/pop's. There's not much to go on, when adding such metadata.
I love Smalltalk, Objective-C, and having a rich runtime system with reflection, meta-data, garbage collection, etc. Amazing code can be written to take advantage of these facilities! But that's simply a higher layer on the stack, a layer that must rest on lower layers, that themselves must ultimately sit upon the OS and the hardware. And we will always need a language that is best suited for building that layer: C++/C/Assembler.
The reason C++ doesn't have reflection is that this would require the compilers to add symbol information to the object files, like what members a class type has, information about the members, about the functions and everything. This essentially would render include files useless, as information shipped by declarations would then be read from those object files (modules then). In C++, a type definition can occur multiple times in a program by including the respective headers (provided that all those definitions are the same), so it would have to be decided where to put the information about that type, just as to name one complication here. The aggressive optimization done by a C++ compiler, which can optimize out dozens of class template instantiations, is another strong point. It's possible, but as C++ is compatible to C, this would become an awkward combination.
Certainly the reflection I am referring to would not cover the semantic meaning or more complex issues (like comments source code line numbers, data flow analysis, etc) - but neither do I think those are needed to be part of a language standard.
The above list is not exhaustive and we are open to further suggestions. For myself, I would love to see Cryptography and Stream API's make it into Phobos, but I am sure that the list of what the community wants to add is legion so those could end up being lower priority.
If so, I guess the default Allocator will be the GC one, and can still be disabled. Being able to change the default (or change locally like in a function or pass it as parameter) would provide a lot of flexibility.
08ab062aa8