
An Introduction to Reflection in C++ - frostmatthew
http://jackieokay.com/2017/04/13/reflection1.html
======
jstimpfle
> 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).

~~~
StillBored
C++ has "built in" serialization the same way that C does.. Except its not
acceptable to use anymore, even though its orders of magnitude faster than the
alternatives.. AKA you write your structures out directly as binary data.
Bonus if you align them. The limitation is that you can't have
classes/structures with actual pointers in them (rather using offsets) and you
have to encourage your compiler to pack/align them consistently. Bonus if you
override the new/placement allocator so that you can serialize gigabytes of
data (including pointers) with a simple map/unmap call.

Frankly, the idea that data should be human readable is complete crap,
especially for things which are going to be machine processed far more than
human processed. AKA use XML for your config file, not for the gigabytes of
data you send over the wire/store on disk/etc, that will never be read by a
human. Its funny that HTML/etc has everyone in this strange mindset that
somehow its more efficient to build human readable markup, which 99.9999% of
the time is never read by a human, and has to be compressed with algorithms
that further burn up tons of CPU time in order to squash the resulting data.
The untold tons of carbon wasted transfering more data than necessary and/or
compressing/decompressing it is insane for the possibility that someone will
want to read it as it flys over the wire, rather than decoding it at the
endpoint and viewing it in a debugger...

~~~
frozenport
Dumping raw binary is a problem if you want your data to be readable across
platforms or versions of the same code.

It is also a bad idea if reading a complete structure into memory is not
possible, or a poor use of time. For example, if you need to read a single
part of a gigabyte data set.

~~~
StillBored
None of this is a show stopper, especially with a little planning. AKA pad the
structures a bit initially, or put version numbers in them. Even if you fail
to do any of that early on, it can be bolted on with a bit of preprocessing as
part of a version upgrade. Its really no different than a schema change
between version numbers. Plus, if your really paranoid, you verify field size
and offsets at startup time against a previously generated bit of metadata.

Also, if you happen to need to pick out a tiny bit of data from some huge
tree/whatever data structure then map it with appropriate madvise() and simply
let the kernel page in the portions you need to access. The whole dataset
doesn't need to be read to pick out a couple bytes here and there. Further if
this is a common use case you probably shouldn't be using this method anyway,
rather storing the index separately from the data in a manner which allows
them to be accessed independently. This mechanism holds up for multiple TB
sized datasets, and can be tuned by playing with the amount of physical ram in
the machine vs the speed of the disk. Then when storage class memory takes
off, you don't even have to rewrite your application.

Finally, for a single GB dataset, doing a bulk read is likely well under a 1
second operation on most reasonable storage mechanisms available for server
use. Compared with picking off a couple hundred thousand fields from an object
storage mechanism this is going to seem pretty speedy.

------
NotSammyHagar
I 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.

~~~
dasloop
What 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
Like D?

~~~
dasloop
No, 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".

------
Profan
A 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/)

------
Kenji
I 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.

~~~
bsaul
i'm not sure about your particular issue, but every time i had to choose
between being smart and generic with serialization over being straightforward
and boring ( at the cost of writing one small line of code for each and every
property), i always choose to stay boring.

Not only is it nicer to the person that's going to maintain your code and may
not know about your smart trick, but with generic code there is _always_ an
exception that makes you need to write some code somewhere that breaks the
abstraction.

~~~
maxxxxx
Same here. Generic serialization often breaks when there are some changes to
the data and you have to be compatible with different versions.

------
swift
The 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
True, I will correct this in the article.

------
tcbawo
Is 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
Be 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
Generally 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).

------
0xFFC
>$, 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".

~~~
adrift
It's a matter of taste; for me 'reflexpr' is about as disgusting as
'constexpr'.

~~~
0xFFC
No it is not matter of taste. I dont have anything against $ in php, perl, or
most other languages. But it is not consistent with C++ syntax at all.

------
heinrich5991
What blogging engine is that? It looks nice.

~~~
carc1n0gen
Looks like one of the standard jekyll themes. I could be wrong though

~~~
keerthiko
Yep:
[https://github.com/jacquelinekay/jacquelinekay.github.io](https://github.com/jacquelinekay/jacquelinekay.github.io)

