Lumiera  0.pre.03
»edit your freedom«
opaque-holder.hpp File Reference

Go to the source code of this file.

Description

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.

Managed opaque placement buffer

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

Lightweight passively managed opaque holder buffer

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

See also
opaque-holder-test.cpp
function-erasure.hpp usage example
variant.hpp

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 <cstddef>
#include <utility>
#include <type_traits>

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 >
 

Functions

template<typename X >
enable_if< is_constructible< bool, X >, bool > validitySelfCheck (X const &boolConvertible)
 
template<typename X >
disable_if< is_constructible< bool, X >, bool > validitySelfCheck (X const &)
 

Namespaces

 lib
 Implementation namespace for support and library code.
 

Class Documentation

◆ lib::InPlaceBuffer::TypeTag

struct lib::InPlaceBuffer::TypeTag
+ Collaboration diagram for InPlaceBuffer< BA, siz, DEFAULT >::TypeTag< TY >: