Live data from Hacker News

Reflection in C++14: Explanations

blog.simon-ninon.fr

31–37 of 37 posts

Re: Reflection in C++14: Explanations

#31
post #30

Earlier quoted context omitted.

I think the term "zero cost abstraction" is a bit misleading. Abstraction means that developers don't have to think about some lower level aspects that they would have given some thought otherwise. That tends to result in inefficiencies. For instance, C programmers will think a lot more about the size of buffers, how big they need to be, can they be fixed size, can they be reused, etc, because expanding them is often…

I dont think I agree. Abstraction in my view is (mostly) about removing implementation details that dont change from one implementation to another. Its about removing boilerplate until just the fundamental features of the implementations remain. It would be a bad abstraction if details (low level or otherwise) that do change, are removed. Im not sure I get your example. Are you implying that this C++ code is ineffici…

>If you know the size of result in advance, there is no reason to use a stream for result.

Oh yes there is a reason. The reason is that streams are a convenient abstraction because there is very likely an operatorYou are absolutely right, that this can be implemented a lot more efficiently. That's exactly my point. Abstractions lure us into using inefficient solutions without thinking.

You say "If you know the size of result in advance [...]". Well, exactly. Do you? That's something C programmers think about long and hard but you don't have to think about it if you use streams or even string abstractions naively.

This isn't just a case of "you can write bad code in any language". It's what abstractions do. Allow us to ignore stuff that is unnecessary if the goal is simply to arrive at a correct but less efficient solution.

Re: Reflection in C++14: Explanations

#32
I found myself recently needing to embed an open source library which used a similar mechanism for its plugin system. The goals of the plugin design of this system were to make it possible to cleanly register plugins for a range of different types in a manner which preserved type safety and to be able to use the same registration mechanism to define any of these plugins within arbitrary compilation units so that plugins could be easily added by consumers of the system -- using the same mechanism as used for the built in plugins... Including for plugins loaded at runtime.

The plugin registration mechanism involves a pre processor macro that authors invoke on each plugin class after definition -- this macro declares that the specified plugin implements a special factoryinstance template class. The factoryinstance template class is paramterized by the plugin type and the specific plugin implementation and provides a default constructor that retrieves the class name of the plugin implementation class via the qt meta object system and adds it to a central registry for each plugin type. This template class also contains a static member variable of the self same factoryinstance template class. This member variable gets initialized by default by the compiler during static initialization which causes the default constructor for the specialized type to be called which causes the plugin to be added to a registry with correct name and correct type information intact ...

This was all well and good however had a very annoying consequence for me as i wanted to embed some of the functionality of this system into a reusable static archive (the original system authors were only concerned with shared library scenarios). At the end of the day no code linking against this archive will make any reference to any symbols of any of these template class implementations -- so the linker will strip all these symbols away and remove all the static initialization calls -- leaving an empty plugin registry in the runtime environment of The final binary ...

For now I work around the issue by requiring that each consumer of the static library pass linker flags to force load the whole static -- this works however makes the binaries larger than needed as each binary must include all plugins and the linker is not able to include just the ones used ... At some point I'm going to need to figure out the smallest set of changes to this registration mechanism to adapt this library to the embedded use case such that a consumer of the library will include only the plugins they use ... I haven't figured out what that looks like yet ...

This issue was kind of a mind warping ... Sometimes the more I learn about C++, the more insane it seems ...

Re: Reflection in C++14: Explanations

#33
A lot of people commented about the JSON configuration file and I'd like to clarify this part of the article.

The routing configuration through a JSON configuration file was an idea I had at the beginning and it lead me to reflexion. I found the subject quite challenging and interesting, and I decided to work on it, resulting in a reflexion library.

However, when I came back to the original library, the mvc framework, I did not decide to go further concerning this routing configuration for multiple reasons: 1. the additional cost for each route call, resulting in decreased performance. 2. even if configuration would have been easier with JSON (or whatever) configuration file, the developer would have to register his controllers and actions for reflexion: lots of complexity for no real gain, as you have mentioned. And of course, if we want to avoid registering step, we would fall back in the dlopen solution as explained in the article, not really more appreciable.

I will maybe do an update to clarify this because lots of people seem to give a real importance to this part while it was only a way for me to introduce the subject. The goal of this article was mainly to describe briefly possible implementations of reflexion in C++, especially the one I have worked on.

Re: Reflection in C++14: Explanations

#34

So here's my advice on the writing an article like this: Show the result first, then explain how you arrived there! Otherwise some readers will end up frustrated with the solution after absorbing tons of detail, and others will have given up even though they might have liked the result.

Thank you for your advice! This is my real first article (I've never written articles as long as this one before, and I've never written articles in English earlier), so these kind of feedbacks are really interesting :)

Re: Reflection in C++14: Explanations

#35
post #27

I had to write some introspection system for a project a while ago. It wasn't the same use case and calling by name wasn't even required. It was more about handling random object from an unified interface issue. Anyway, here is an extreme oversimplified introspection engine I just wrote. It only implement creating wrapper "generic" object by class name. While we both used some of the same tricks, I have a few more th…

With some basic method calling and argument registration

https://gist.github.com/Elv13/fa854e502c6c076f6bb8

REGISTER_METHOD(MyClass, myMethod3) NO_ARG

REGISTER_METHOD(MyClass, myMethod ) ARG(std::string) ARG(std::string) NO_ARG

REGISTER_METHOD(MyClass, myMethod2) RET(int) NO_ARG

Without boost preprocessor!

/me ok, time to stop wasting time on this. Please, myself, forget about this and go to sleep

Re: Reflection in C++14: Explanations

#37
post #20

Earlier quoted context omitted.

Then why do the solutions people use to work around the absence of reflection always seem to suck so much? They're (in some combination) verbose, highly un-DRY, require spectacular feats of type-system-fu, and at the end of the day they deliver capabilities that come up laughably short of their competition in other languages. I'm still waiting for a member of the "Reflection is Useless" crowd to show me a serializati…

The best apprach is to have "reflection" (really, access to the compiler AST or IR) at compile time and generate code from this, since that minimizes the run-time overhead. See Rust's serde for an example of that for serialization.

Let us know when someone implements anything remotely in the same league as Apple's XCode (based on Interface Builder, which first appear ~25 years ago) for designing GUIs using this technique. The fact that it doesn't exist should tell you something.
Post reply on HN