2011-04-21 19:35:09 +02:00
/*
2019-04-14 15:38:57 +02:00
POLYMORPHIC - VALUE . hpp - building opaque polymorphic value objects
2011-04-21 19:35:09 +02:00
Copyright ( C ) Lumiera . org
2011 , Hermann Vosseler < Ichthyostega @ web . de >
This program is free software ; you can redistribute it and / or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation ; either version 2 of
the License , or ( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/** @file polymorphic-value.hpp
* * A mechanism to allow for opaque polymorphic value objects .
2012-11-25 02:04:19 +01:00
* * This template helps to overcome a problem occasionally encountered in
2011-04-23 20:19:29 +02:00
* * C + + programming , based on the fundamental design of C + + , which favours
2011-04-21 19:35:09 +02:00
* * explicit low - level control , copying of values and strict ctor - dtor pairs .
* * Many object oriented design patterns build on polymorphism , where the
* * actual type of an object isn ' t disclosed and collaborations rely on
* * common interfaces . This doesn ' t mix well with the emphasis the C / C + +
* * language puts on efficient handling of small data elements as values
* * and explicit control of the used storage ; indeed several of the modern
* * object oriented and functional programming techniques more or less
* * assume the presence of a garbage collector or similar mechanism ,
* * so ' objects ' need just to be mentioned by reference .
* *
2011-12-10 03:13:45 +01:00
* * In C + + , in order to employ many of the well known techniques , we ' re bound
* * more or less to explicitly put the objects somewhere in heap allocated memory
2011-04-21 19:35:09 +02:00
* * and then pass an interface pointer or reference into the actual algorithm .
2012-11-25 02:04:19 +01:00
* * Sometimes , this hinders a design based on constant values and small descriptor
2011-04-21 19:35:09 +02:00
* * objects used inline , thus forcing into unnecessarily complex and heavyweight
* * alternatives . While it ' s certainly pointless to fight the fundamental nature
* * of the programming language , we may try to pull some ( template based ) trickery
* * to make polymorphic objects fit better with the handling of small copyable
* * value objects . Especially , C + + gives a special meaning to passing parameters
2019-05-10 16:32:56 +02:00
* * as ` const & ` - - typically constructing an anonymous temporary object conveniently
2011-04-21 19:35:09 +02:00
* * just for passing an abstraction barrier ( while the optimiser can be expected to
* * remove this barrier and the accompanying nominal copy operations altogether in
2011-04-23 20:19:29 +02:00
* * the generated code ) . Consequently the ability to return a polymorphic object
* * from a factory or configuration function < i > by value < / i > would open a lot of
2011-04-21 19:35:09 +02:00
* * straight forward design possibilities and concise formulations .
* *
2019-04-20 22:23:55 +02:00
* * # how to build a copyable value without knowing it ' s layout in detail
2011-04-21 19:35:09 +02:00
* *
* * So the goal is to build a copyable and assignable type with value semantics ,
* * without disclosing the actual implementation and object layout at the usage site .
2011-04-23 20:19:29 +02:00
* * This seemingly contradictory goal can be achieved , provided that
2011-04-21 19:35:09 +02:00
* * - the space occupied by the actual implementation object is limited ,
* * so it can be placed as binary data into an otherwise opaque holder buffer
* * - and the actual implementation object assists with copying and cloning
2011-04-23 20:19:29 +02:00
* * itself , observing the actual implementation data layout
* *
2015-03-21 02:00:55 +01:00
* * The PolymorphicValue template implements this idea , by exposing a copyable
2011-04-23 20:19:29 +02:00
* * container with value semantics to the client code . On instantiation , a common
* * base interface for the actual value objects needs to be provided ; the resulting
* * instance will be automatically convertible to this interface . Obviously this
* * common interface must be an ABC or at least contain some virtual functions .
* * Moreover , the PolymorphicValue container provides static builder functions ,
* * allowing to place a concrete instance of a subclass into the content buffer .
* * After construction , the actual type of this instance will be forgotten
2019-05-10 16:32:56 +02:00
* * ( " type erasure " ) , but because of the embedded vtable , on access , the
2011-04-23 20:19:29 +02:00
* * proper implementation functions will be invoked .
* *
* * Expanding on that pattern , the copying and cloning operations of the whole
* * container can be implemented by forwarding to appropriate virtual functions
* * on the embedded payload ( implementation ) object - - the concrete implementation
* * of these virtual functions can be assumed to know the real type and thus be
* * able to invoke the correct copy ctor or assignment operator . For this to
* * work , the interface needs to expose those copy and clone operations somehow
2019-04-14 15:38:57 +02:00
* * as virtual functions . There are two alternatives to fulfil this requirement :
2011-04-23 20:19:29 +02:00
* * - in the general case , the common base interface doesn ' t expose such operations .
2019-04-14 15:38:57 +02:00
* * Thus we need to _mix in_ an additional _management_ interface ; this
* * can be done by _subclassing_ the desired implementation type , because
2011-04-23 20:19:29 +02:00
* * this concrete type is irrelevant after finishing the placement constructor .
* * In order to re - access this management interface , so to be able to invoke
* * the copy or clone operations , we need to do an elaborate re - cast operation ,
2012-11-25 02:04:19 +01:00
* * first going down to the leaf type and then back up into the mixed - in
2011-04-23 20:19:29 +02:00
* * management interface . Basically this operation is performed by using
2019-04-14 15:38:57 +02:00
* * a ` dynamic_cast < CopyAPI & > ( bufferContents ) `
2011-04-23 20:19:29 +02:00
* * - but when the used client types provide some collaboration and implement
* * this management interface either directly on the API or as an immediate
* * sub - interface , then this copy / management interface is located within the
2019-04-14 15:38:57 +02:00
* * direct inheritance chain and can be reached by a simple ` static_cast ` .
2011-04-23 20:19:29 +02:00
* * Indeed , as we ' re just using a different meaning of the VTable , only a
* * single indirection ( virtual function call ) is required at runtime in
* * this case to invoke the copy ctor or assignment operator .
2011-04-24 20:28:36 +02:00
* * Thus , in this latter ( optimal ) case , the fact that PolymorphicValue allows
* * to conceal the actual implementation type comes with zero runtime overhead ,
2019-04-14 15:38:57 +02:00
* * compared to direct usage of a family of polymorphic types ( with VTable ) .
2011-04-24 20:28:36 +02:00
* *
2012-11-25 02:04:19 +01:00
* * So , how can the implementation of copy or assignment know the actual type
* * to be copied ? Basically we exploit the fact that the actual instance lives
2019-04-14 15:38:57 +02:00
* * in an opaque buffer within the " outer " container . More specifically , _we_
2012-11-25 02:04:19 +01:00
* * place it into that buffer - - thus we ' re able to control the actual type used .
* * This way , the actual copy operations reside in an Adapter type , which lives
* * at the absolute leaf end of the inheritance chain . It even inherits from
* * the " implementation type " specified by the client . Thus , within the
2019-04-14 15:38:57 +02:00
* * context of the copy operation , we know all the concrete types .
2012-11-25 02:04:19 +01:00
* *
2019-04-20 22:23:55 +02:00
* * @ todo the actual implementation for copy support basically achieves this goal ,
* * but it is somewhat confusing and muddled , and not entirely correct in some
* * corner cases ( esp . when the target type does _not collaborate_ but also
* * does _only support copy construction_ , but no assignment .
* * In fact , part of the solution implemented here is known as " virtual copy
* * support " ; meanwhile we use a generic version of that pattern in our
* * [ Variant container ] ( \ ref variant . hpp ) . Thus , at some point , we should
* * rework this aspect of the solution to make it more orthogonal , clearer
* * to understand and more correct . /////////////////////////////////////////////TICKET #1197
* *
2012-11-25 02:04:19 +01:00
* *
2019-04-14 15:38:57 +02:00
* * # using polymorphic value objects
2011-04-24 20:28:36 +02:00
* *
* * To start with , we need a situation where polymorphic treatment and type erasure
* * might be applicable . That is , we use a public API , and only that , in any client
* * code , while the concrete implementation is completely self contained . Thus , in
* * the intended use , the concrete implementation objects can be assembled once ,
* * typically in a factory , and after that , no further knowledge of the actual
* * implementation type is required . All further use can be coded against
* * the exposed public API .
* *
* * Given such a situation , it might be desirable to conceal the whereabouts of
* * the implementation completely from the clients employing the generated objects .
* * For example , the actual implementation might rely on a complicated subsystem
* * with many compilation dependencies , and we don ' t want to expose all those
* * details on the public API .
* *
* * Now , to employ PolymorphicValue in such a situation , on the usage side ( header ) :
* * - expose the public API , but not the implementation type of the objects
* * - define an instantiation of PolymorphicValue with this API
* * - be sure to define a hard wired size limit not to be exceeded by the
* * actual implementation objects ( PolymorphicValue ' s ctor has an assertion
* * to verify this constraint )
* * - provide some kind of factory for the clients to get the actual polymorphic
* * value instances . Clients may then freely move and copy those objects , but
* * do not need to know anything about the actual implementation object layout
* * ( it could be figured out using RTTI though )
* *
* * On the implementation side ( separate compilation unit )
* * - include the definition of the PolymorphicValue instantiation ( of course )
* * - define the implementation types to inherit from the public API
* * - implement the mentioned factory function , based on the static build
* * PolymorphicValue # build functions , using the actual implementation type
2019-04-14 15:38:57 +02:00
* * as parameter .
2011-04-21 19:35:09 +02:00
* *
* * @ see polymorphic - value - test . cpp
* * @ see opaque - holder . hpp other similar opaque inline buffer templates
* * @ see lib : : time : : Mutation usage example
*/
# ifndef LIB_POLYMORPHIC_VALUE_H
# define LIB_POLYMORPHIC_VALUE_H
# include "lib/error.hpp"
2011-04-23 20:19:29 +02:00
# include "lib/meta/duck-detector.hpp"
2017-02-11 23:40:26 +01:00
# include "lib/util.hpp"
2011-04-21 19:35:09 +02:00
namespace lib {
2011-04-24 20:28:36 +02:00
namespace polyvalue { // implementation details...
2011-04-23 20:19:29 +02:00
2011-04-25 04:49:05 +02:00
namespace error = lumiera : : error ;
2017-08-11 20:23:46 +02:00
using lib : : meta : : enable_if ;
2011-12-03 02:56:50 +01:00
using lib : : meta : : Yes_t ;
using lib : : meta : : No_t ;
2011-04-23 20:19:29 +02:00
struct EmptyBase { } ;
2011-04-24 20:28:36 +02:00
/**
* Interface for active support of copy operations
* by the embedded client objects . When inserted into the
2019-04-14 15:38:57 +02:00
* inheritance chain _above_ the concrete implementation objects ,
2011-04-24 20:28:36 +02:00
* PolymorphicValue is able to perform copy operations trivially and
2019-04-14 15:38:57 +02:00
* without any ` dynamic_cast ` and other run time overhead besides a
2011-04-24 20:28:36 +02:00
* simple indirection through the VTable . To enable this support , the
2019-04-14 15:38:57 +02:00
* implementation objects should inherit from ` CopySupport < Interface > `
* ( where ` Interface ` would be the public API for all these embedded
2011-04-24 20:28:36 +02:00
* implementation objects ) .
* Alternatively , it ' s also possible to place this CopySupport API as parent
* to the public API ( it might even be completely absent , but then you ' d need
* to provide an explicit specialisation of the Traits template to tell
* PolymorphicValue how to access the copy support functions . )
*/
template < class IFA ///< the common public interface of all embedded objects
, class BA = IFA ///< direct baseclass to use for this copy support API
2011-04-23 20:19:29 +02:00
>
class CopySupport
: public BA
{
public :
virtual ~ CopySupport ( ) { } ;
virtual void cloneInto ( void * targetBuffer ) const = 0 ;
virtual void copyInto ( IFA & targetBase ) const = 0 ;
} ;
2011-04-25 04:49:05 +02:00
/**
* A variation for limited copy support .
* Sometimes , only cloning ( copy construction ) of value objects is allowed ,
* but not assignment of new values to existing objects . In this case , the
* concrete values can inherit from this variant of the support API .
*/
template < class BA > ///< direct baseclass to use for this clone support API
class CloneValueSupport
: public BA
{
public :
virtual ~ CloneValueSupport ( ) { } ;
virtual void cloneInto ( void * targetBuffer ) const = 0 ;
} ;
2019-04-20 22:23:55 +02:00
///////////////////////////////////////////////TICKET #1197 : this should be a full "virtual copy support" to cover all possible cases
2011-04-23 20:19:29 +02:00
2016-07-21 19:29:16 +02:00
/**
2011-04-24 20:28:36 +02:00
* helper to detect presence of a function
* to support clone operations
*/
2011-04-23 20:19:29 +02:00
template < typename T >
2011-04-25 04:49:05 +02:00
class exposes_CloneFunction
2011-04-23 20:19:29 +02:00
{
2019-05-10 02:19:01 +02:00
META_DETECT_FUNCTION_NAME ( cloneInto ) ;
2011-04-23 20:19:29 +02:00
public :
2019-05-10 02:19:01 +02:00
enum { value = HasFunName_cloneInto < T > : : value
} ; // warning: match on the function name only
2011-04-23 20:19:29 +02:00
} ;
2011-04-25 04:49:05 +02:00
/**
* helper to detect if the API supports only
* copy construction , but no assignment
*/
template < typename T >
class allow_Clone_but_no_Copy
{
META_DETECT_MEMBER ( copyInto ) ;
public :
enum { value = exposes_CloneFunction < T > : : value
& & ! HasMember_copyInto < T > : : value
} ;
} ;
2011-04-21 19:35:09 +02:00
2011-04-25 04:49:05 +02:00
/**
* Policy class for invoking the assignment operator .
* By default the embedded payload objects are assumed
* to be freely assignable
*/
template < class API , class YES = void >
struct AssignmentPolicy
{
template < class IMP >
2019-04-14 15:38:57 +02:00
static void
2011-04-25 04:49:05 +02:00
assignEmbedded ( IMP & dest , IMP const & src )
{
dest = src ;
}
} ;
/**
* special case when the embedded payload objects permit
* copy construction , but no assignment to existing instances .
* Instead of invoking the assignment operator ( which typically
* isn ' t defined at all in such cases ) , a misguided assignment
* to the container will raise an exception
*/
template < class API >
2017-08-11 20:23:46 +02:00
struct AssignmentPolicy < API , enable_if < allow_Clone_but_no_Copy < API > > >
2011-04-25 04:49:05 +02:00
{
template < class IMP >
2019-04-14 15:38:57 +02:00
static void
2011-04-25 04:49:05 +02:00
assignEmbedded ( IMP & , IMP const & )
{
throw error : : Logic ( " attempt to overwrite unmodifiable value " ) ;
}
} ;
/**
2019-05-10 16:32:56 +02:00
* trait template to deal with different ways to support copy operations .
2011-04-24 20:28:36 +02:00
* Default is no support by the API and implementation types .
2019-05-10 16:32:56 +02:00
* In this case , the CopySupport interface is mixed - in at the
* level of the concrete implementation class and will be
* accessed later on through a ` dynamic_cast < CopyAPI & > `
2019-04-20 22:23:55 +02:00
* @ todo this whole decision logic works but is confusingly written ///////////////////////TICKET #1197 : improve design of copy support
2011-04-24 20:28:36 +02:00
*/
2019-04-14 15:38:57 +02:00
template < class TY , class YES = void >
2011-04-23 20:19:29 +02:00
struct Trait
{
2019-05-10 16:32:56 +02:00
using CopyAPI = CopySupport < TY , EmptyBase > ; ///////////////////////////TICKET #1197 : this is naive, we do not know if the target really has full copy support...
using Assignment = AssignmentPolicy < CopyAPI > ;
using AdapterAttachment = CopyAPI ;
enum { ADMIN_OVERHEAD = 2 * sizeof ( void * ) } ; // need second VTable for CopyAPI mix-in
2011-04-23 20:19:29 +02:00
static CopyAPI &
accessCopyHandlingInterface ( TY & bufferContents )
{
REQUIRE ( INSTANCEOF ( CopyAPI , & bufferContents ) ) ;
2011-04-24 20:28:36 +02:00
return dynamic_cast < CopyAPI & > ( bufferContents ) ;
2011-04-23 20:19:29 +02:00
}
} ;
2011-04-24 20:28:36 +02:00
/**
* Special case when the embedded types support copying
2019-04-14 15:38:57 +02:00
* on the API level , e . g . there is a sub - API exposing a ` cloneInto `
2011-04-24 20:28:36 +02:00
* function . In this case , the actual implementation classes can be
* instantiated as - is and the copy operations can be accessed by a
2019-04-14 15:38:57 +02:00
* simple ` static_cast ` without runtime overhead .
2011-04-24 20:28:36 +02:00
*/
2011-04-23 20:19:29 +02:00
template < class TY >
2017-08-11 20:23:46 +02:00
struct Trait < TY , enable_if < exposes_CloneFunction < TY > > >
2011-04-23 20:19:29 +02:00
{
2019-05-10 16:32:56 +02:00
using CopyAPI = TY ;
using Assignment = AssignmentPolicy < CopyAPI > ;
using AdapterAttachment = struct { /* irrelevant */ } ;
enum { ADMIN_OVERHEAD = 1 * sizeof ( void * ) } ; // just the VTable of the payload
2011-04-23 20:19:29 +02:00
template < class IFA >
static CopyAPI &
accessCopyHandlingInterface ( IFA & bufferContents )
{
REQUIRE ( INSTANCEOF ( CopyAPI , & bufferContents ) ) ;
2011-04-24 20:28:36 +02:00
return static_cast < CopyAPI & > ( bufferContents ) ;
2011-04-23 20:19:29 +02:00
}
} ;
2011-04-21 19:35:09 +02:00
2011-04-24 20:28:36 +02:00
} //(End)implementation details
2011-04-21 19:35:09 +02:00
2011-04-25 04:49:05 +02:00
2011-04-21 19:35:09 +02:00
/**
* Template to build polymorphic value objects .
* Inline buffer with value semantics , yet holding and owning an object
* while concealing the concrete type , exposing only the public interface .
* Access to the contained object is by implicit conversion to this public
* interface . The actual implementation object might be placed into the
* buffer through a builder function ; later , this buffer may be copied
* and passed on without knowing the actual contained type .
2011-04-24 20:28:36 +02:00
*
2019-04-14 15:38:57 +02:00
* For using PolymorphicValue , several * assumptions * need to be fulfilled
* - any instance placed into the opaque buffer is below the specified maximum size
2011-04-21 19:35:09 +02:00
* - the caller cares for thread safety . No concurrent get calls while in mutation !
*
* @ warning when a create or copy - into operation fails with exception , the whole
2011-12-10 03:13:45 +01:00
* PolymorphicValue object is in undefined state and must not be used henceforth .
2011-04-21 19:35:09 +02:00
*/
template
< class IFA ///< the nominal Base/Interface class for a family of types
2011-04-23 20:19:29 +02:00
, size_t storage ///< maximum storage required for the target data to be held inline
, class CPY = IFA ///< special sub-interface to support copy operations
2011-04-21 19:35:09 +02:00
>
class PolymorphicValue
{
2019-05-10 16:32:56 +02:00
private :
2011-04-23 20:19:29 +02:00
typedef polyvalue : : Trait < CPY > _Traits ;
typedef typename _Traits : : CopyAPI _CopyHandlingAdapter ;
2019-04-20 22:23:55 +02:00
typedef typename _Traits : : Assignment _AssignmentPolicy ; /////////////////TICKET #1197 : confusingly indirect decision logic
2019-04-14 15:38:57 +02:00
enum {
siz = storage + _Traits : : ADMIN_OVERHEAD
2011-04-23 20:19:29 +02:00
} ;
2019-10-11 20:26:02 +02:00
// WARNING: never add any member fields here /////////////////TICKET #1204
2011-04-23 20:19:29 +02:00
2011-04-24 20:28:36 +02:00
/* === embedded object in buffer === */
/** Storage for embedded objects */
2011-04-21 19:35:09 +02:00
mutable char buf_ [ siz ] ;
2011-04-24 20:28:36 +02:00
IFA &
accessEmbedded ( ) const
2011-04-21 19:35:09 +02:00
{
2011-04-24 20:28:36 +02:00
return reinterpret_cast < IFA & > ( buf_ ) ;
2011-04-21 19:35:09 +02:00
}
void
2011-04-24 20:28:36 +02:00
destroyEmbedded ( )
2011-04-21 19:35:09 +02:00
{
2011-04-24 20:28:36 +02:00
accessEmbedded ( ) . ~ IFA ( ) ;
2011-04-21 19:35:09 +02:00
}
2011-04-24 20:28:36 +02:00
/**
2019-04-14 15:38:57 +02:00
* Implementation Helper : add support for copy operations .
2011-04-24 20:28:36 +02:00
* Actually instances of this Adapter template are placed
* into the internal buffer , such that they both inherit
2019-04-14 15:38:57 +02:00
* from the desired implementation type and the copy
2011-04-24 20:28:36 +02:00
* support interface . The implementation of the
* concrete copy operations is provided here
2019-04-14 15:38:57 +02:00
* as forwarding to the copy operations
* of the implementation object .
2011-04-24 20:28:36 +02:00
*/
2011-04-21 19:35:09 +02:00
template < class IMP >
class Adapter
: public IMP
2011-04-24 20:28:36 +02:00
, public _Traits : : AdapterAttachment // mix-in, might be empty
2011-04-21 19:35:09 +02:00
{
virtual void
cloneInto ( void * targetBuffer ) const
{
2011-04-24 20:28:36 +02:00
new ( targetBuffer ) Adapter ( * this ) ; // forward to copy ctor
2011-04-21 19:35:09 +02:00
}
virtual void
copyInto ( IFA & targetBase ) const
{
REQUIRE ( INSTANCEOF ( Adapter , & targetBase ) ) ;
Adapter & target = static_cast < Adapter & > ( targetBase ) ;
2011-04-25 04:49:05 +02:00
_AssignmentPolicy : : assignEmbedded ( target , * this ) ;
2019-04-14 15:38:57 +02:00
} // forward to assignment operator
2011-04-21 19:35:09 +02:00
2011-04-24 20:28:36 +02:00
public : /* == forwarding ctor to implementation type == */
2019-04-16 16:40:38 +02:00
template < typename . . . ARGS >
Adapter ( ARGS & & . . . args )
: IMP ( std : : forward < ARGS > ( args ) . . . )
{ }
2011-04-24 20:28:36 +02:00
/* using default copy and assignment */
2011-04-21 19:35:09 +02:00
} ;
2019-04-16 16:40:38 +02:00
template < typename IMP >
using TypeSelector = Adapter < IMP > * ;
2011-04-21 19:35:09 +02:00
2011-04-23 20:19:29 +02:00
_CopyHandlingAdapter &
2011-04-21 19:35:09 +02:00
accessHandlingInterface ( ) const
{
2011-04-24 20:28:36 +02:00
IFA & bufferContents = accessEmbedded ( ) ;
return _Traits : : accessCopyHandlingInterface ( bufferContents ) ;
2011-04-21 19:35:09 +02:00
}
2019-04-16 16:40:38 +02:00
/**
* @ internal this is the actual working ctor , which must care to decorate
* the desired impl type with an additional adapter to support copy operations .
*/
template < class IMP , typename . . . ARGS >
PolymorphicValue ( TypeSelector < IMP > , ARGS & & . . . args )
{
static_assert ( siz > = sizeof ( Adapter < IMP > ) , " insufficient inline buffer size " ) ;
new ( & buf_ ) Adapter < IMP > ( std : : forward < ARGS > ( args ) . . . ) ;
}
protected :
/**
* @ internal ctor for subclasses and builder functions .
* The constructor requires an additional type - selector argument .
* On invocation , the desired subclass / implementation object is immediately
* planted into the embedded buffer , passing through the given ctor arguments .
* @ see [ factory functions for public use ] ( \ ref PolymorphicValue : : build )
*/
template < class IMP , typename . . . ARGS >
PolymorphicValue ( IMP * , ARGS & & . . . args )
: PolymorphicValue ( TypeSelector < IMP > ( ) , std : : forward < ARGS > ( args ) . . . )
{ }
2011-04-23 20:19:29 +02:00
2011-04-24 20:28:36 +02:00
public : /* === PolymorphicValue public API === */
typedef IFA Interface ;
2019-05-11 18:08:00 +02:00
Interface &
getPayload ( )
{
return accessEmbedded ( ) ;
}
2011-04-24 20:28:36 +02:00
operator Interface & ( )
2011-04-21 19:35:09 +02:00
{
2011-04-24 20:28:36 +02:00
return accessEmbedded ( ) ;
2011-04-21 19:35:09 +02:00
}
2011-04-24 20:28:36 +02:00
operator Interface const & ( ) const
2011-04-21 19:35:09 +02:00
{
2011-04-24 20:28:36 +02:00
return accessEmbedded ( ) ;
}
Interface *
operator - > ( ) const
{
return & ( accessEmbedded ( ) ) ;
2011-04-21 19:35:09 +02:00
}
~ PolymorphicValue ( )
{
2011-04-24 20:28:36 +02:00
destroyEmbedded ( ) ;
2011-04-21 19:35:09 +02:00
}
PolymorphicValue ( PolymorphicValue const & o )
{
o . accessHandlingInterface ( ) . cloneInto ( & buf_ ) ;
}
PolymorphicValue &
operator = ( PolymorphicValue const & o )
{
2011-04-24 20:28:36 +02:00
o . accessHandlingInterface ( ) . copyInto ( this - > accessEmbedded ( ) ) ;
2011-04-21 19:35:09 +02:00
return * this ;
}
2011-04-24 20:28:36 +02:00
/* === static factory functions === */
2019-04-16 16:40:38 +02:00
template < class IMP , typename . . . ARGS >
2011-04-21 19:35:09 +02:00
static PolymorphicValue
2019-04-16 16:40:38 +02:00
build ( ARGS & & . . . args )
2011-04-21 19:35:09 +02:00
{
2011-08-15 00:52:12 +02:00
Adapter < IMP > * type_to_build_in_buffer ( 0 ) ;
2019-04-16 16:40:38 +02:00
return PolymorphicValue ( type_to_build_in_buffer , std : : forward < ARGS > ( args ) . . . ) ;
2011-04-21 19:35:09 +02:00
}
2011-04-24 20:28:36 +02:00
/* === support Equality by forwarding to embedded === */
2011-04-21 19:35:09 +02:00
friend bool
operator = = ( PolymorphicValue const & v1 , PolymorphicValue const & v2 )
{
2011-04-24 20:28:36 +02:00
return v1 . accessEmbedded ( ) = = v2 . accessEmbedded ( ) ;
2011-04-21 19:35:09 +02:00
}
friend bool
operator ! = ( PolymorphicValue const & v1 , PolymorphicValue const & v2 )
{
2015-09-25 02:38:59 +02:00
return not ( v1 = = v2 ) ;
2011-04-21 19:35:09 +02:00
}
} ;
} // namespace lib
# endif