
Reflection in C++14: Explanations - cylix
http://blog.simon-ninon.fr/reflection-in-c-plus-plus-14/
======
userbinator
_I didn’t want the developer to declare his routes by writing C++ code_

...in a _web framework in C++_ , where presumably the developer would need to
write C++ anyway to make use of it?

 _This article is quite long and complex_

No kidding. And to me, all that complexity just screams "you're doing it
wrong."

I read this article all the way to the end, and was disappointed to find that,
after all that code, it ends with a single macro call --- in C++ --- and
leaves the reader wondering about the original goal of using JSON.

Years ago I spent a brief amount of time maintaining Java code that was
written in this reflection-heavy, everything-configurable (XML and even some
ad-hoc text formats, but similar idea) style, and it was not at all enjoyable
to get everything set up correctly nor debug the monstrosity. On a somewhat
related note,
[http://discuss.joelonsoftware.com/default.asp?joel.3.219431....](http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12&)

~~~
iabacu
_I’d prefer to have a simple JSON configuration file..._ followed by a pile of
unnecessary complexity in the form of new semantics on how to declare and tie
things together.

I highly doubt that this is making author's developers life easier.

More likely, it's just an over-engineering indulgence, that happens to make
one's job more secure.

------
ajkjk
I prefer the C++ configuration over the reflective one. It plays nicely with
IDEs and tooling; I can use a debugger on it; I can run code while generating
it; it gets verified by type-checking; etc. The only thing it doesn't have is
the familiarity bonus of JSON.

------
Animats
So, in the end, you have a system which allows a JSON data structure to call
arbitrary C++ functions. Is that a good thing? That JSON is now highly
trusted. And do you really want to program in JSON?

This is essentially a rather complicated way to build an interpreter for
another language. To display web pages. Sort of like PHP.

This might be worth the trouble if you were using it to allow programmable
shaders in a renderer. Those are usually composed of functional blocks strung
together, they have to go very fast, and they're composed by people who are
artists, not programmers, often through some GUI. There, it might not be
overkill.

------
cylix
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.

------
tuyguntn
I appreciate effort given by author, but sorry it seems like "how to guide":

How to kill your time by making simple things complex, then how to kill more
time by maintaining it, then how to kill more and more time for adding one
small feature.

------
fauigerzigerk
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.

~~~
cylix
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 :)

------
something123
Yikes.. I'm going to have to reread this later to grok it better. I think it's
nice that the language has added all these new features (though the macros at
the end tell me it's not enough..) - but I keep feeling like the direction of
the language post-C++11 has been steered by library developers with these more
and more difficult to digest features. Features that you don't end up using
every day, and so they never really sink in.

There are plenty of simpler things I'd like them to tackle before. Just in the
past week of work two examples come to mind (just to illustrate that there are
still issues)

\- I was trying to get some function calls to inline and had to fight the
compiler for half the day to get it to inline them for me (I still don;t
understand why it's okay that the compiler ignored the inline keyword. Can't
we assume that I as the developer will know what's best if I explicitly put
the keyword there?)

\- Then the next day I had the opposite problem where a branch was being
inlined even though I wanted a if(/ _rare event_ /){ jump to some method}.
Again the language provides no tools for me to accomplish that

There are tons of issues with the standard library containers and data
locality that have been ignored too.

C++ is THE high performance language - can we spend some time on performance
and stop pretending that there isn't room for improvement on that front?

------
robohamburger
It makes sense to consider what you make configurable especially when it is
this expensive. I can't imagine routes change that much and when they do they
probably change with code.

This seems like the kind of yak shaving that can really ruin a perfectly good
project.

That isn't to say configuration doesn't have its place! One of the reasons I
love python and interpreted languages is it is very easy to do when you need
it.

------
Elv13
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 that make introspection
simpler. My implementation also work on embedded systems without a working
"dynamic_cast" and C++ runtime type identifier.

[https://gist.github.com/Elv13/715fb1b3dc4b774a06ca](https://gist.github.com/Elv13/715fb1b3dc4b774a06ca)

Edit: Just to clarify, this is a much smaller subset of what you implemented
in the blog post, but it can be extended into a full introspection system
using more lambdas maps and variadic template tricks.

~~~
Elv13
With some basic method calling and argument registration

[https://gist.github.com/Elv13/fa854e502c6c076f6bb8](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

------
et1337
Very cool, but I think you could accomplish this easier using macros from the
start. An example in Objective C: [http://etodd.io/2013/11/26/auto-generating-
json-serializatio...](http://etodd.io/2013/11/26/auto-generating-json-
serialization-code-in-objective-c/)

------
Rickasaurus
Still much grosser than reflection in other languages.

~~~
kybernetyk
Yes, but reflection usually is an ugly hack anyway and if you have to resort
to it something is wrong with your design.

~~~
jjoonathan
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 serialization framework on par with what I find in Java
(100% DRY, 100% automatic for POD, 100% override-able without a type
repository, 100% devoid of compiler/linker trickery). Or a desktop framework
that offers UI design capabilities comparable to the introspection-based ones
I find in ObjC, C#, or whatever you want to call the home-brew C++-with-
reflection that Qt uses.

~~~
devit
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.

------
Svenstaro
I applaud your effort and I actually like your result but this just shows how
much we need real reflection in C++17. I like to use C++ for its performance
and the recent standards were a big leap in the right direction but reflection
just isn't one of C++'s strengths.

~~~
maikklein
Afaik reflection doesn't make it into C++17.

~~~
Svenstaro
Nuuuh. :(

------
breatheoften
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 ...

------
jlarocco
I wonder how long it'll be before C++ loses its performance advantages. It
used to be low level enough that just using it meant you probably got a pretty
good performance boost. But if they keep adding features like variants and
reflection, and if people actually start using them, it seems like performance
will necessarily decline.

Or, if not, other languages will look at C++ to see how they handle these
features and keep performance, and improve their compilers.

~~~
userbinator
If C++ "loses its performance advantages" it will entirely be due to the
culture and not the language itself, because you can still do inline assembler
in C++. I've long believed that the reason why lower-level languages have
performance advantages is because their paucity of "rich" features means their
users often find simpler, more efficient ways of solving problems.

I've noticed this even between C++ and C - without classes, inheritance, and
so forth, you tend to think a lot more about whether you need something class-
like before going ahead and doing it, and many times a simple function is all
you need.

Adding new features almost certainly invites plenty of advocates who will
opine about how much better they are (which is true in some situations),
encourating their use, even if not actually necessary. This is problematic
when these features make it easy to generate large amounts of inefficient
code.

~~~
petke
People often think of C++ as a Object oriented language. That a very old
fashioned way at looking at it. Most modern C++ code avoids OOP like the
plague. For instance the author of STL (The C++ standard template library)
calls OOP, philosophically unsound, a hoax.

[http://www.stlport.org/resources/StepanovUSA.html](http://www.stlport.org/resources/StepanovUSA.html)

------
nexys
for stuff like this you can use Lua, what is the main difference with the
solution exposed on the post?

