kentonv/capnproto — pull request #41 by amluto (2013-10-29 23:30:11+00:00)
Title: Add EImpl (food for thought)

EImpl is a template I wrote awhile ago to encapsulate incomplete types.
It's IMO a lot prettier than the hack it replaces, and it's difficult to
misuse. I reformatted it a bit and added a noexcept(false) destructor for
kj's benefit.

Downsides:
- It pulls in for std::aligned_storage. is
relatively short and has no major dependencies, at least in libstdc++ 4.8.
With some (not-quite-portable) hackery, it could be avoided. Alternatively,
if the default alignment were removed, then it could be replaced by
alignas, but gcc 4.7 doesn't support that.

- Noexcept handling is imperfect.

Upsides:
- This could be used in a lot more places in capnp and kj, and it could
compilation time and reduce the need for ABI-breaking (or ODR-violating)
changes down the road.

The idiom I've used is:

class Whatever {
public:
// ...

struct Impl;
EImpl impl_;
};

Using a public EImpl has a major benefit: it reduces the need for friend
declarations while still protecting impl_ from prying eyes.

My in-house version has some (ugly) macros to get at the parent class
from &impl_. This seems to be rarely useful.

This may be useful for various cleanups. For example, MessageBuilder and MessageReader could use it instead of

void* arenaSpace[15 + sizeof(kj::MutexGuarded) / sizeof(void*)];

You'd replace it with something like:

kj::Maybe)>> arena;

This isn't currently viable (without hacks) because Maybe is (AFAICS) missing the ability to construct things in place. That would be easy to add, though.