8 ms·
An Introduction to Reflection in C++
- heinrich5991 10y agoWhat blogging engine is that? It looks nice.
- carc1n0gen 10y agoLooks like one of the standard jekyll themes. I could be wrong though
- keerthiko 10y agoYep: https://github.com/jacquelinekay/jacquelinekay.github.io https://github.com/jacquelinekay/jacquelinekay.github.io
- NotSammyHagar 10y agoI learned some things from reading that article. I hadn't heard about those other schemes to do rtti. I just want it to be as easy as objective c was, and I still like those smalltalk like api calls that were in that. But the article reminds me why I still feel frustrated that my programming work is divided between java and c++. There are so many things that are easy in java and hugely painful in c++, and c++ slowly adds those ideas yet it makes the language more painful to use over time. I basically want to throw c++ away and replace it with something that is more regular and doesn't expose so many complexities to the end programmer like the endless nuances of memory allocation, moving, &&, r values etc. But there's no hope of that. For the rest of my life every year or two there will be additions to c++ that I will have learn about and use and gradually discover their own warts, yet java will still keep cruising along.
- quinnftw 10y agoCruising along with frequent pit stops for garbage collection. All jokes aside I agree with you to some extent: C++ can be frustrating to work with, and there are a lot of quirks that make it really easy to blow your foot off. These quirks are not without benefit though. Being able to control how memory is allocated is hugely important in performance sensitive applications where pointer chasing is not tolerable. The same can be said about r values/move semantics.
- Rusky 10y agoYou can get those benefits without the complexity of C++ if you're willing to break with the past (and as for the newer features, it's possible C++ could have implemented them more straightforwardly, though maybe they were already designed into a corner). For example, look at C++'s concept of move semantics. The language still runs destructors regardless of whether a value has been moved. This means every movable class has to have a valid "empty" state the destructor can check to avoid double frees. That means you need move constructors which can run arbitrary code. And that means generic code that does moves has to care about exception safety. Instead, the language could statically avoid running the destructors of moved values. No more rvalue zoo needed to trigger a move, no more mandatory "empty" states because the destructor can assume a valid object, no more move constructors because they all reduce to memcpy, and thus no more exception safety problems and an easier job for the optimizer.
- asveikau 10y agoIf you implement a move as a swap (as in the examples I saw when I first heard of move constructors back when it was called c++0x) you don't need an empty state. Not being able to keep track of what cases call a destructor and which ones do not sounds like a much more huge problem than the one you are talking about. Doesn't seem too hard to avoid the temptation throw in a move constructor.
- Rusky 10y agoYou can't always swap. For example, you may want to use a movable but non-copyable type to keep un-aliased access to a single resource (see linear/affine types) and the compiler treating the move source as dead is useful there. Or maybe you don't want to allocate anything for the move target because the resource you're managing is expensive. Keeping track of when a destructor gets called is not a huge problem at all. From the user perspective it's airtight, proper uninitialized value analysis in the compiler make it impossible to screw up. From the implementation perspective all you need is the occasional flag on the stack (whose value is already calculated) for situations like `if ... { use_by_move(obj) }`, and a rule against moving things out of fields that you're otherwise not responsible for destructing (you can still swap there).
- dasloop 10y agoWhat I want is a language over C++, as typescript is over JavaScript, that keeps compatibility with C and C++ code (Qt, boost...) and provides a clear syntax and some advanced features (as reflection) even paying a price for it. This is it, no more zero cost abstraction.
- lossolo 10y agoLike D?
- dasloop 10y agoNo, D is a separate language. A bit too much. Ideally you will be able to move between a version of the language or another at Class level to alllow a incremental migration of the code that must be "modernized".
- deleted 10y ago[deleted]
- NotSammyHagar 10y agoThat is a great idea and great metaphor to describe your new language.
- mabynogy 10y agoI'm doing that but it's more a CoffeScript than a Typescript (no semicolons and no commas). An example: fn add(x1 x2) { return <x1+x2> } fn <main>(count:int arguments:<const char** const>):int { (<printf> "%d\n" (add 2 3)) return 0 } Is converted to: auto add(const auto x1,const auto x2) { return x1+x2; } int main(const int count, const char** const arguments) { printf("%d\n",add(2,3)); return 0; } Everything inside the <angle brackets> is left as is in the C++ output. I use S-expressions for function calls.
- smitherfield 10y agoCython? http://cython.org http://cython.org Yes, it supports C++ (even templates!): http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html http://docs.cython.org/en/latest/src/userguide/wrapping_CPlu...
- eru 10y agoHave you had a look at D, yet?
- Kenji 10y agoI am writing a game engine and C++'s lack of proper reflection is a real hindrance for a variety of serialisation/deserialisation interfaces, be it networking or saving things to disk and loading them. You just end up writing redundant and more brittle code for no reason other than that a language feature is missing. I think it is great that this problem is given attention. Edit: After thinking on it for a few minutes. All I want is a generic function that takes a class as the generic type T, and a string as an argument, and returns me a completely filled in object of type T, or throws an error on malformed input. I really don't think I am asking for too much here.
- TillE 10y ago> All I want is a generic function that takes a class as the generic type T, and a string as an argument, and returns me a completely filled in object of type T, or throws an error on malformed input. Well, what you need is a way to enumerate the members of a class. Everything else is already done by something like Cereal or Boost.Serialization.
- kuschku 10y agoUsually you might want to instead use code generation at compile time to do these things, even in Java. Reflection is always magnitudes slower.
- caseymarquis 10y ago.NET allows you to use reflection to emit bytecode which does the same work as reflection. More complicated to setup, but the speed-up is huge. Not sure if Java has an equivalent? I'd be curious to know.
- barrkel 10y agoYes. You generate bytecode for classes that are loaded by a class loader, and thereby enter the JIT world etc. The tech predates .NET, but it isn't as developer friendly as DynamicMethod etc.
- 10y ago
- Profan 10y agoA shame that D[1] wasn't mentioned under other alternatives as it has a comprehensive system for compile-time introspection built in! [1] http://dlang.org/ http://dlang.org/
- 0xFFC 10y ago>$, as a way of getting object metadata out of a class, namespace, etc. (Using $ has been argued out of favor because it is common in legacy code, particularly in code generation and template systems which are not necessarily valid C++ but produce C++ sources.) you have got to be kidding me, right ? "$" adding this character too to the C++ ? What left we haven't add ? Why not use only something like "reflexpr" which is more C++ish than $ character. Why make C++ more difficult to parse and read with every release ? TBH I genuinely don't understand why we need both ? why not only have "reflexpr".
- foonathan 10y ago$ is already a valid identifier character in a clang and gcc extension. And there won't be reflexpr and $, those are two different proposal. And due to the extension, it won't be $ (most likely).
- 0xFFC 10y agoThank you. I really hope so.
- adrift 10y agoIt's a matter of taste; for me 'reflexpr' is about as disgusting as 'constexpr'.
- marvy 10y ago> What haven't we added yet? There's also the @ sign and the backtic `. I think that's it for ASCII.
- swift 10y agoThe author made a small mistake in this article which may be worth pointing out: -fno-rtti does not disable the generation of vtables (which would break virtual method dispatch) but only runtime type information. The two are connected in that RTTI is generally stored with an object's vtable, so objects with no virtual methods don't get it. The alternative would be to include a pointer to type information in all objects without a vtable, but the amount of memory this would require would be substantial, and it would break expectations about the size and memory layout of "plain old data" structs.
- jackiek 10y agoTrue, I will correct this in the article.
- jstimpfle 10y ago> It would be really nice to compose objects hierarchally: for example, if I had a widget class composed of several different renderable Rectangles, I want to be able to automatically generate the rendering code for my widget based on the existing rendering logic for its constituent shapes. So one thing that I've learned about programming: Don't overthink it. How many different object types do you want to serialize? Maybe a hundred? So just write those 100 lines of boilerplate. Not a huge amount of work, even when there is the the occasional modification. An additional benefit is that you're not painting yourself in a corner - for example, you can leave out that additional bit of redundant information that you hacked in as an optimization. What's really huge for maintainability is this thing called aspect-oriented programming: Don't litter each of your classes with a line of boilerplate for this and another line for that. Make a file "serialize.cpp" that contains the serialization code for all the types, and nothing else. In other words, object-oriented is the wrong tool, for almost everything (sorry if that's old news).
- twoodfin 10y agoHopefully the next version of the C++ standard will incorporate some form of the unified call syntax proposal, which will make the use of this style of code organization more consistent with traditional one-per-class declaration files.
- SolarNet 10y ago> > It would be really nice to compose objects hierarchally: for example, if I had a widget class composed of several different renderable Rectangles, I want to be able to automatically generate the rendering code for my widget based on the existing rendering logic for its constituent shapes. Actually, what's interesting is that both Lisp macros and C++ templates allow this to work pretty easily if you set up the boiler plate well enough. All this article is really talking about is making it easier to set up and use that boilerplate (e.g. put it in the language). > What's really huge for maintainability is this thing called aspect-oriented programming: Don't litter each of your classes with a line of boilerplate for this and another line for that. Make a file "serialize.cpp" that contains the serialization code for all the types, and nothing else. And that works if your project is not meant to ever be extended. But generally the point of having object oriented systems is being able to make new objects that can take the place of old ones. Of having abstraction.
- tcbawo 10y agoIs anyone doing a strong constexpr hash for use in compile-time serialization? It would be impressive to combine compile-time serialization with a consistent method of evaluating type differences. I've heard of people doing this with a dedicated compile/link step.
- a_t48 10y agoBe careful with doing this - the serialized identifier for the type needs to be separate from the type name or else you can never rename.
- fsloth 10y agoGenerally trying to come up with complex compile time higher level abstractions in C++ is a waste of time. A better idea is to figure out a relational schema for the runtime presentation of the data and represent that with a combination of standard datastructures and PODs. I really, really would see mental efforts spent in systems design and simplifying the problem and not in findindg the best way to contort C++ to some other languages paradigm (on the compiler level - runtime behaviour for any complex dynamic data might start to appear like lisp but please don't try to make the compiler understand that).