Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
Helper allowing type erasure while holding the actual object inline.
Controlling the actual storage of objects usually binds us to commit to a specific type, thus ruling out polymorphism. But sometimes, when we are able to control the maximum storage for a family of classes, we can escape this dilemma by using the type erasure pattern combined with an inline buffer holding an object of the concrete subclass. Typically, this situation arises when dealing with functor objects.
These templates help with building custom objects and wrappers based on this pattern: lib::InPlaceAnyHolder provides a buffer for target objects and controls access through a two-layer capsule; while the outer container exposes a neutral interface, the inner container keeps track of the actual type by means of a vtable. OpaqueHolder is built on top of InPlaceAnyHolder additionally to support a "common base interface" and re-access of the embedded object through this interface. For this to work, all of the stored types need to be derived from this common base interface. OpaqueHolder then may be even used like a smart-ptr, exposing this base interface. To the contrary, InPlaceAnyHolder has lesser requirements on the types to be stored within. It can be configured with policy classes to control the re-access; when using InPlaceAnyHolder_unrelatedTypes the individual types to be stored need not be related in any way, but of course this rules out anything beyond re-accessing the embedded object by knowing it's exact type. Generally speaking, re-accessing the concrete object requires knowledge of the actual type, similar to boost::any (but contrary to OpaqueHolder the latter uses heap storage).
As a supplement, a more lightweight implementation is provided as lib::InPlaceBuffer, requiring just the object storage and lacking the ability to track the actual type of the embedded object, and the buffer can not be empty with this model – which turns out to be adequate in most usage scenarios. This kind of lightweight "inline buffer" can even be exposed on API through a lib::PlantingHandle, allowing an arbitrary client to plant an likewise opaque implementation subclass into the buffer, as long as the storage size constraint is observed.
Using this approach is bound to specific stipulations regarding the properties of the contained object and the kind of access needed. When, to the contrary, the contained types are not related and you need to re-discover their concrete type, then maybe a visitor or variant record might be a better solution.
TICKET #1204 : proper alignment verified 10/2019
Definition in file opaque-holder.hpp.
#include "lib/error.hpp"
#include "lib/nocopy.hpp"
#include "lib/access-casted.hpp"
#include "lib/meta/util.hpp"
#include "lib/util.hpp"
#include <boost/lexical_cast.hpp>
#include <type_traits>
#include <utility>
Classes | |
struct | InPlaceAnyHolder< siz, AccessPolicy >::Buff< SUB > |
concrete subclass to manage a specific kind of contained object. More... | |
struct | InPlaceAnyHolder< siz, AccessPolicy >::Buffer |
Inner capsule managing the contained object (interface) More... | |
struct | InPlaceAnyHolder< siz, AccessPolicy >::EmptyBuff |
special case: no stored object More... | |
class | InPlaceAnyHolder< siz, AccessPolicy > |
Inline buffer to hold and own an object while concealing the concrete type. More... | |
struct | InPlaceAnyHolder_unrelatedTypes |
Alternative policy for accessing the contents without a common interface; use this policy if the intention is to use OpaqueHolder with a family of similar classes, without requiring all of them to be derived from a common base class. More... | |
struct | InPlaceAnyHolder_useCommonBase< BA > |
Standard policy for accessing the contents via a common base class interface. More... | |
class | InPlaceBuffer< BA, siz, DEFAULT > |
Buffer to place and maintain an object instance privately within another object. More... | |
class | OpaqueHolder< BA, siz > |
Inline buffer to hold and own an object while concealing the concrete type. More... | |
class | PlantingHandle< BA, DEFAULT > |
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBuffer, without having to disclose the concrete buffer type or size. More... | |
class | PlantingHandle< BA, DEFAULT > |
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBuffer, without having to disclose the concrete buffer type or size. More... | |
struct | InPlaceBuffer< BA, siz, DEFAULT >::TypeTag< TY > |
Namespaces | |
lib | |
Implementation namespace for support and library code. | |
struct lib::InPlaceBuffer::TypeTag |