77 #ifndef LIB_OPAQUE_HOLDER_H 78 #define LIB_OPAQUE_HOLDER_H 87 #include <boost/lexical_cast.hpp> 89 #include <type_traits> 96 using error::LERR_(BOTTOM_VALUE);
97 using error::LERR_(WRONG_TYPE);
106 using lib::meta::disable_if;
107 using std::is_constructible;
110 enable_if< is_constructible<bool,X>,
112 validitySelfCheck (X
const& boolConvertible)
114 return bool(boolConvertible);
118 disable_if< is_constructible<bool,X>,
120 validitySelfCheck (X
const&)
144 convert2base (SUB& obj)
151 throw error::Logic (
"Unable to convert concrete object to Base interface" 174 convert2base (SUB& obj)
176 return static_cast<void*
> (&obj);
211 typedef typename AccessPolicy::Base * BaseP;
217 void* ptr() {
return &content_; }
220 virtual bool isValid()
const =0;
221 virtual bool empty()
const =0;
222 virtual BaseP getBase()
const =0;
224 virtual void clone (
void* targetStorage)
const =0;
230 virtual bool isValid()
const {
return false; }
231 virtual bool empty()
const {
return true; }
237 , LERR_(BOTTOM_VALUE));
241 clone (
void* targetStorage)
const 250 template<
typename SUB>
253 static_assert (siz >=
sizeof(SUB),
"InPlaceAnyHolder: insufficient Buffer size");
258 return *
reinterpret_cast<SUB*
> (unConst(
this)->ptr());
267 Buff (SUB
const& obj)
269 new(Buffer::ptr()) SUB (obj);
274 new(Buffer::ptr()) SUB (oBuff.
get());
288 clone (
void* targetStorage)
const 290 new(targetStorage)
Buff(
get());
296 return AccessPolicy::convert2base (
get());
308 return validitySelfCheck (this->
get());
314 enum{ BUFFSIZE =
sizeof(
Buffer) };
319 char storage_[BUFFSIZE];
331 return *
reinterpret_cast<Buffer*
> (&storage_);
336 return *
reinterpret_cast<const Buffer *
> (&storage_);
349 new(&storage_) EmptyBuff();
354 place_inBuff (SUB
const& obj)
356 new(&storage_) Buff<SUB> (obj);
362 ref.buff().clone (storage_);
368 BaseP asBase = buff().getBase();
410 if (not isSameObject (*
this, ref))
428 operator= (SUB
const& newContent)
431 or not isSameObject (*buff().getBase(), newContent)
437 place_inBuff (newContent);
461 typedef const Buffer* Iface;
462 typedef const Buff<SUB> * Actual;
463 Iface
interface = &buff();
464 Actual actual =
dynamic_cast<Actual
> (interface);
466 return actual->get();
470 ,LERR_(BOTTOM_VALUE));
472 throw error::Logic (
"Attempt to access OpaqueHolder's contents " 473 "specifying incompatible target type" 483 return buff().empty();
490 return buff().isValid();
494 operator bool()
const 535 ,
size_t siz =
sizeof(BA)
550 operator= (SUB
const& newContent)
552 static_cast<InPlaceHolder&
>(*this) = newContent;
565 ASSERT (!InPlaceHolder::empty());
566 return *InPlaceHolder::buff().getBase();
572 ASSERT (!InPlaceHolder::empty());
573 return InPlaceHolder::buff().getBase();
583 template<
class BA,
class DEFAULT>
610 ,
size_t siz =
sizeof(BA)
617 mutable char buf_[siz];
623 return reinterpret_cast<BA&
> (buf_);
629 static_assert (siz >=
sizeof(DEFAULT),
"InPlaceBuffer too small");
631 new(&buf_) DEFAULT();
653 template<
class TY,
typename...ARGS>
656 static_assert (siz >=
sizeof(TY),
"InPlaceBuffer too small");
658 new(&buf_) TY (std::forward<ARGS> (args)...);
665 template<
typename SUB>
673 template<
class TY,
typename...ARGS>
677 static_assert (siz >=
sizeof(TY),
"InPlaceBuffer too small");
681 return *
new(&buf_) TY {std::forward<ARGS> (args)...};
695 static_assert (siz >=
sizeof(SUB),
"InPlaceBuffer too small");
699 return *
new(&buf_) SUB {std::forward<SUB> (implementation)};
713 return static_cast<DEFAULT&
> (getObj());
738 BA * asBase = &getObj();
763 template<
class BA,
class DEFAULT = BA>
769 static_assert (std::has_virtual_destructor<BA>(),
770 "target interface BA must provide virtual dtor, " 771 "since InPlaceBuffer needs to take ownership.");
774 void __ensure_can_create();
778 template<
size_t maxSiz>
780 : buffer_(&targetBuffer)
791 static_assert(std::is_base_of<BA,SUB>(),
"concrete object implanted into the opaque " 792 "buffer must implement the defined interface");
793 return sizeof(SUB) <= maxSiz_;
801 __ensure_can_create<SUB>();
804 Holder& holder = *
static_cast<Holder*
> (buffer_);
806 return holder.template emplace (std::forward<SUB> (implementation));
810 template<
class SUB,
typename...ARGS>
814 __ensure_can_create<SUB>();
817 Holder& holder = *
static_cast<Holder*
> (buffer_);
819 return holder.template create<SUB> (std::forward<ARGS> (args)...);
828 return &bufferContent;
837 template<
class BA,
class B0>
842 if (not this->canCreate<SUB>())
843 throw error::Fatal(
"Unable to implant implementation object of size " 844 "exceeding the pre-established storage buffer capacity. " 845 +boost::lexical_cast<std::string>(
sizeof(SUB)) +
" > " 846 +boost::lexical_cast<std::string>(maxSiz_)
847 ,error::LUMIERA_ERROR_CAPACITY);
Helper template to access a given value, possibly converted or casted in a safe way.
TY & create(ARGS &&...args)
Abbreviation for placement new.
Any copy and copy construction prohibited.
virtual ~Buffer()
this is an ABC with VTable
SUB & create(ARGS &&...args)
Abbreviation for placement new of a subclass SUB into the opaque buffer.
SUB & get() const
< core operation: target is contained within the inline buffer
Implementation namespace for support and library code.
InPlaceBuffer(TY *, ARGS &&...args)
immediately emplace an embedded subclass type
Inline buffer to hold and own an object while concealing the concrete type.
Derived specific exceptions within Lumiera's exception hierarchy.
SUB & emplace(SUB &&implementation)
move-construct an instance of a subclass into the opaque buffer
Inline buffer to hold and own an object while concealing the concrete type.
SUB & emplace(SUB &&implementation)
move-construct an instance of subclass into the opaque buffer
Mix-Ins to allow or prohibit various degrees of copying and cloning.
A handle to allow for safe »remote implantation« of an unknown subclass into a given opaque InPlaceBu...
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Lumiera error handling (C++ interface).
Inner capsule managing the contained object (interface)
Standard policy for accessing the contents via a common base class interface.
void __ensure_can_create()
Buffer to place and maintain an object instance privately within another object.
special case: no stored object
static auto embedType()
helper to mark the subclass type to create.
concrete subclass to manage a specific kind of contained object.
Helper for accessing a value, employing either a conversion or downcast, depending on the relation of...
bool isSameObject(A const &a, B const &b)
compare plain object identity, bypassing any custom comparison operators.