Library: allow for subclassing PolymorphicValue

Up to now, PolymorphicValue was always used as-is, packaged into a typedef.
Now we consider using it as building block within an adapter for visitor-like tokens.

Which requires to pass-down the ctor call directly from the subclass, at least if we
want to emplace the resulting entity directly into a stdlib container.

As an asside, PolymorphicValue also used explicit specialisations for N-arguments,
which meanwhile can be replaced by variadic templates
This commit is contained in:
Fischlurch 2019-04-16 16:40:38 +02:00
parent ec9b2388da
commit 500af8aa34

View file

@ -389,36 +389,6 @@ namespace lib {
} }
template<class IMP>
PolymorphicValue (IMP*)
{
static_assert (siz >= sizeof(IMP), "insufficient inline buffer size");
new(&buf_) IMP();
}
template<class IMP, typename A1>
PolymorphicValue (IMP*, A1 a1)
{
REQUIRE (siz >= sizeof(IMP));
new(&buf_) IMP (a1);
}
template<class IMP, typename A1, typename A2>
PolymorphicValue (IMP*, A1 a1, A2 a2)
{
REQUIRE (siz >= sizeof(IMP));
new(&buf_) IMP (a1,a2);
}
template<class IMP, typename A1, typename A2, typename A3>
PolymorphicValue (IMP*, A1 a1, A2 a2, A3 a3)
{
REQUIRE (siz >= sizeof(IMP));
new(&buf_) IMP (a1,a2,a3);
}
/** /**
* Implementation Helper: add support for copy operations. * Implementation Helper: add support for copy operations.
* Actually instances of this Adapter template are placed * Actually instances of this Adapter template are placed
@ -450,20 +420,17 @@ namespace lib {
public: /* == forwarding ctor to implementation type == */ public: /* == forwarding ctor to implementation type == */
Adapter() : IMP() { } template<typename...ARGS>
Adapter (ARGS&&... args)
template<typename A1> : IMP(std::forward<ARGS>(args)...)
Adapter (A1 a1) : IMP(a1) { } { }
template<typename A1, typename A2>
Adapter (A1 a1, A2 a2) : IMP(a1,a2) { }
template<typename A1, typename A2, typename A3>
Adapter (A1 a1, A2 a2, A3 a3) : IMP(a1,a2,a3) { }
/* using default copy and assignment */ /* using default copy and assignment */
}; };
template<typename IMP>
using TypeSelector = Adapter<IMP>*;
_CopyHandlingAdapter& _CopyHandlingAdapter&
accessHandlingInterface () const accessHandlingInterface () const
@ -472,6 +439,31 @@ namespace lib {
return _Traits::accessCopyHandlingInterface (bufferContents); return _Traits::accessCopyHandlingInterface (bufferContents);
} }
/**
* @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)...)
{ }
public: /* === PolymorphicValue public API === */ public: /* === PolymorphicValue public API === */
@ -510,36 +502,12 @@ namespace lib {
/* === static factory functions === */ /* === static factory functions === */
template<class IMP> template<class IMP, typename...ARGS>
static PolymorphicValue static PolymorphicValue
build () build (ARGS&&... args)
{ {
Adapter<IMP>* type_to_build_in_buffer(0); Adapter<IMP>* type_to_build_in_buffer(0);
return PolymorphicValue (type_to_build_in_buffer); return PolymorphicValue (type_to_build_in_buffer, std::forward<ARGS>(args)...);
}
template<class IMP, typename A1>
static PolymorphicValue
build (A1 a1)
{
Adapter<IMP>* type_to_build_in_buffer(0);
return PolymorphicValue (type_to_build_in_buffer, a1);
}
template<class IMP, typename A1, typename A2>
static PolymorphicValue
build (A1 a1, A2 a2)
{
Adapter<IMP>* type_to_build_in_buffer(0);
return PolymorphicValue (type_to_build_in_buffer, a1,a2);
}
template<class IMP, typename A1, typename A2, typename A3>
static PolymorphicValue
build (A1 a1, A2 a2, A3 a3)
{
Adapter<IMP>* type_to_build_in_buffer(0);
return PolymorphicValue (type_to_build_in_buffer, a1,a2,a3);
} }