Library: complete test coverage of VerbPack

This commit is contained in:
Fischlurch 2019-05-11 18:08:00 +02:00
parent 3d5a67ed14
commit f6e5886348
9 changed files with 427 additions and 223 deletions

View file

@ -1530,7 +1530,7 @@ namespace lib {
* which for the consumer side behave like `iterNext()` calls. If a layer needs to do something special for
* `iterNext()`, it needs to perform a similar action for `expandChildren()`.
* - it must be behave like a default-constructible, copyable value object
* @return augmented TreeExplorer, incorporating and adpting the injected layer
* @return augmented TreeExplorer, incorporating and adapting the injected layer
*/
template<template<class> class LAY>
auto

View file

@ -477,6 +477,12 @@ namespace lib {
typedef IFA Interface;
Interface&
getPayload()
{
return accessEmbedded();
}
operator Interface& ()
{
return accessEmbedded();

View file

@ -113,7 +113,7 @@ namespace lib {
}
Literal const&
getID()
getID() const
{
return token_;
}

View file

@ -111,18 +111,28 @@ namespace lib {
}
/** Building block: the Interface to cause the invocation */
template<class REC, class RET>
struct VerbInvoker
: polyvalue::CloneValueSupport<polyvalue::EmptyBase> // mark and mix-in virtual copy construction support
{
virtual ~VerbInvoker() { }
virtual RET applyTo (REC&) =0;
virtual RET applyTo (REC&) =0;
virtual Literal getID() const =0;
bool operator== (VerbInvoker const& o) const { return getID() == o.getID(); }
bool operator!= (VerbInvoker const& o) const { return getID() != o.getID(); }
};
template<class REC, class SIG>
struct VerbHolder;
/**
* Building block: actual storage for a "verb" (function pointer),
* together with the pre-bound invocation arguments for this specific operation.
*/
template<class REC, class RET, typename... ARGS>
struct VerbHolder<REC, RET(ARGS...)>
: VerbInvoker<REC,RET>
@ -134,13 +144,21 @@ namespace lib {
/** meta-sequence to pick argument values from the storage tuple */
using SequenceIterator = typename meta::BuildIdxIter<ARGS...>::Ascending;
/** Storage for the argument tuple */
Args args_;
VerbHolder (typename Verb::Handler handlerRef, Literal verbID, ARGS&&... args)
template<typename...PARS>
VerbHolder (typename Verb::Handler handlerRef, Literal verbID, PARS&&... args)
: Verb{handlerRef, verbID}
, args_{std::forward<ARGS> (args)...}
, args_{std::forward<PARS> (args)...}
{ }
Literal
getID() const override
{
return Verb::getID();
}
RET
applyTo (REC& receiver) override
{
@ -148,45 +166,88 @@ namespace lib {
}
private:
/** @internal actual function invocation, thereby unpacking the argument tuple */
template<size_t...idx>
RET
invokeVerb (REC& receiver, meta::IndexSeq<idx...>)
{ //////////////////////////////////////////TICKET #1006 | TICKET #1184 why do we need std::forward here? the target is a "perfect forwarding" function, which should be able to receive a LValue reference to the tuple element just fine...
return (receiver.*Verb::handler_)(std::get<idx> (args_)...);
{
return (receiver.*Verb::handler_) (std::get<idx> (args_)...);
}
};
/******************************************************************************************//**
* A self-contained token to embody a specific yet abstracted operation,
* together with a concrete set of suitable arguments. The concrete operation
* is suppled on invocation, when the VerbPack is combined with an actual _receiver_
* object, implementing the interface `REC` and thus providing the function implementation.
* VerbPack represents a kind of double-dispatch, flexible both on the actual operation
* (embodied into the given VerbPack object) and also flexible in the concrete receiver.
* @tparam REC the "visitor interface" to invoke operations on
* @tparam RET expected (common) return value of the bound operations (can be `void`)
* @tparam arg_storage maximum storage size to reserve as buffer for actual function parameters.
* @remarks
* - binding an operation with arguments exceeding `arg_storage` triggers a static assertion
* - the resulting VerbPack object has value semantics and is copyable, to the extent any
* embedded function arguments are copyable by themselves.
*/
template<class REC, class RET, size_t arg_storage>
class VerbPack
: public PolymorphicValue<VerbInvoker<REC,RET>, storageOverhead(arg_storage)>
{
using PolyHolder = PolymorphicValue<VerbInvoker<REC,RET>, storageOverhead(arg_storage)>;
using Dispatcher = VerbInvoker<REC,RET>; // the interface to talk to our payload
using PolyHolder = PolymorphicValue<Dispatcher, storageOverhead(arg_storage)>;
template<typename FUN>
struct HandlerTypeDetector
{
static_assert (!sizeof(FUN), "handler must be a function member pointer for the given receiver");
};
template<typename...ARGS>
using PayloadType = VerbHolder<REC, RET(ARGS...)>*;
struct HandlerTypeDetector<RET (REC::*) (ARGS...)>
{
using Verb = VerbToken<REC, RET(ARGS...)>;
using Payload = VerbHolder<REC, RET(ARGS...)>;
};
template<typename FUN>
using PayloadType = typename HandlerTypeDetector<FUN>::Payload *;
template<typename...ARGS>
using Handler = typename VerbToken<REC, RET(ARGS...)>::Handler;
public:
template<typename...ARGS>
VerbPack (Handler<ARGS...> handler, Literal verbID, ARGS&&... args)
: PolyHolder(PayloadType<ARGS...>(), handler, verbID, std::forward<ARGS>(args)...)
/** setup a VerbPack for a given operation on the interface `REC`
* @param handler function member-pointer to define the operation
* @param verbID unique ID to designate the token; equality is based
* on this `verbID`, all tokens with same ID count as equal
* @param args arbitrary (yet suitable) arguments to pre-bind and use later
* when actually invoking the operation on a concrete receiver
*/
template<typename FUN, typename...ARGS>
VerbPack (FUN handler, Literal verbID, ARGS&&... args)
: PolyHolder(PayloadType<FUN>(), handler, verbID, std::forward<ARGS>(args)...)
{ }
/**
* Core operation: invoke the operation for this "verb" with the pre-bound parameters
* @param receiver a subclass of `REC`, providing the function to invoke
* @return result of performing the actual operation
*/
RET
applyTo (REC& receiver)
{
VerbInvoker<REC,RET>& dispatch(*this);
return dispatch.applyTo (receiver);
return PolyHolder::getPayload().applyTo (receiver);
}
operator string() const
{
return "VerbPack("
+ string{util::unConst(this)->getPayload().getID()}
+ ")";
}
};
} // namespace lib
#endif /*LIB_VERB_VISITOR_H*/

View file

@ -740,6 +740,17 @@ return: 0
END
TEST "verb token with embedded arguments" VerbVisitorDispatch_test <<END
out-lit: dispatching VerbPack(woof) -> 'haw-hawhaw-hawhaw-hawhaw-haw'
out-lit: dispatching VerbPack(honk) -> 'quaack-quaack!'
out-lit: dispatching VerbPack(honk) -> 'Hoonk-Hoonk!'
out-lit: dispatching VerbPack(woof) -> 'Woof..Woof..'
out-lit: dispatching VerbPack(moo) -> 'Moo__Moo__Moo'
out-lit: dispatching VerbPack(meh) -> 'Meh?'
return: 0
END
TEST "VectorTransfer_test" VectorTransfer_test <<END
return: 0
END

View file

@ -43,18 +43,20 @@ namespace lib {
namespace test{
class Receiver
{
public:
virtual ~Receiver() { } ///< this is an interface
namespace { // Test Fixture
virtual string woof() =0;
virtual string honk() =0;
virtual string moo() =0;
virtual string meh() =0;
};
/** the "visitor" interface to invoke */
class Receiver
{
public:
virtual ~Receiver() { } ///< this is an interface
virtual string woof() =0;
virtual string honk() =0;
virtual string moo() =0;
virtual string meh() =0;
};
namespace {
const string BEGINNING("silence");
using Verb = VerbToken<Receiver, string(void)>;
@ -65,53 +67,54 @@ namespace test{
Verb VERB(Receiver, honk);
Verb VERB(Receiver, moo);
Verb VERB(Receiver, meh);
}
/**
* a receiver of verb-tokens,
* which renders them verbosely
*/
class VerboseRenderer
: public Receiver
{
string woof() { return "Woof-Woof!"; }
string honk() { return "Honk-Honk!"; }
string moo() { return "Moo-Moo!"; }
string meh() { return "Meh!"; }
};
/**
* a receiver of verb-tokens,
* which renders them verbosely
*/
class VerboseRenderer
: public Receiver
{
string woof() { return "Woof-Woof!"; }
string honk() { return "Honk-Honk!"; }
string moo() { return "Moo-Moo!"; }
string meh() { return "Meh!"; }
};
/**
* Statefull receiver of verb-tokens.
*/
class RecollectingReceiver
: public Receiver
{
string verb_;
_Fmt fmt_;
/**
* Statefull receiver of verb-tokens.
*/
class RecollectingReceiver
: public Receiver
{
string verb_;
_Fmt fmt_;
string
buildResultTerm (string nextToken)
{
string resultExpression (fmt_ % verb_ % nextToken);
verb_ = nextToken;
return resultExpression;
}
string
buildResultTerm (string nextToken)
{
string resultExpression (fmt_ % verb_ % nextToken);
verb_ = nextToken;
return resultExpression;
}
string woof() { return buildResultTerm (VERB_woof); }
string honk() { return buildResultTerm (VERB_honk); }
string moo() { return buildResultTerm (VERB_moo); }
string meh() { return buildResultTerm (VERB_meh); }
string woof() { return buildResultTerm (VERB_woof); }
string honk() { return buildResultTerm (VERB_honk); }
string moo() { return buildResultTerm (VERB_moo); }
string meh() { return buildResultTerm (VERB_meh); }
public:
RecollectingReceiver()
: verb_(BEGINNING)
, fmt_("%s followed by %s")
{ }
};
public:
RecollectingReceiver()
: verb_(BEGINNING)
, fmt_("%s followed by %s")
{ }
};
}//(End) Test fixture

View file

@ -31,118 +31,107 @@
#include "lib/format-string.hpp"
#include "lib/format-cout.hpp"
#include "lib/format-util.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/iter-tree-explorer.hpp"
#include <string>
#include <vector>
#include <tuple>
using std::string;
using util::_Fmt;
using util::join;
using std::vector;
using std::forward;
using std::make_tuple;
namespace lib {
namespace test{
///////////////////////////TODO : Debugging
struct Trackr
{
size_t num;
Trackr (size_t val)
: num(val)
{
cout <<"Trackr("<<val<<")"<<endl;
}
~Trackr()
{
cout <<"~Trackr()"<<endl;
}
Trackr (Trackr const& lval)
: num(lval.num)
{
cout <<"Trackr()<<-LVal"<<endl;
}
Trackr (Trackr && rval)
: num(rval.num)
{
cout <<"Trackr()<<-RVal"<<endl;
}
Trackr&
operator= (Trackr const& orig)
{
cout <<"Tracker = orig"<<endl;
num = orig.num;
return *this;
}
};
///////////////////////////TODO : Debugging
namespace { // Test Fixture
/** the "visitor" interface used by all VerbPacks in this test */
class Receiver
{
public:
virtual ~Receiver() { } ///< this is an interface
virtual string woof (bool huge, uint cnt) =0;
virtual string honk (string) =0;
virtual string moo (size_t num) =0;
virtual string meh () =0;
};
class Receiver
{
public:
virtual ~Receiver() { } ///< this is an interface
virtual string woof (bool huge, uint cnt) =0;
virtual string honk (string) =0;
virtual string moo (Trackr num) =0;
virtual string meh () =0;
};
namespace {
using Token = VerbPack<Receiver, string, sizeof(string)>;
using Token = VerbPack<Receiver, string, sizeof(string)>; // the argument list for honk(string) requires the most inline storage
using TokenSeq = vector<Token>;
}
/**
* a receiver of verb-tokens,
* which renders them verbosely
*/
class VerboseRenderer
: public Receiver
{
string
woof (bool huge, uint cnt) override
{
string woof{huge? "Woof..":"haw-haw"};
while (0 < cnt--)
woof += woof;
return woof;
}
string
honk (string theHonk) override
{
return theHonk+"-"+theHonk+"!";
}
string
moo (Trackr num) override
{
return join (vector<string>{num.num, "Moo"}, "__");
}
string
meh() override
{
return "Meh!";
}
};
/**
* a concrete receiver of verb-tokens,
* which renders them verbosely
*/
class VerboseRenderer
: public Receiver
{
string
woof (bool huge, uint cnt) override
{
string woof;
while (0 < cnt--)
woof += isnil(woof)? string {huge? "Woof..":"haw-haw"}
: woof;
return woof;
}
string
honk (string theHonk) override
{
return theHonk+"-"+theHonk+"!";
}
string
moo (size_t num) override
{
return join (vector<string>{num, "Moo"}, "__");
}
string
meh() override
{
return "Meh?";
}
};
/**
* another concrete receiver to report any invocation with arguments
*/
class DiagnosticRenderer
: public Receiver
{
string woof (bool huge, uint cnt) override { return report("woof", huge, cnt); }
string honk (string theHonk) override { return report("honk", theHonk); }
string moo (size_t num) override { return report("moo", num); }
string meh() override { return report("meh"); }
template<typename...ARGS>
string
report (Literal func, ARGS&&...args)
{
return string(func)
+ meta::dump (make_tuple (forward<ARGS>(args)...));
}
};
}//(End)Test Fixture
#define SHOW_TYPE(_TY_) \
cout << "typeof( " << STRINGIFY(_TY_) << " )= " << lib::meta::typeStr<_TY_>() <<endl;
#define SHOW_EXPR(_XX_) \
cout << "Probe " << STRINGIFY(_XX_) << " ? = " << _XX_ <<endl;
/***********************************************************************//**
* @test Demonstration/Concept: dispatch a specific function
* based on the given verbs of an embedded custom language.
* Actually what we want to achieve here is a specific form
* of double dispatch; thus the implementation relies on a
* variation of the visitor pattern.
* @test Demonstration/Concept: build pre-bound VerbPack objects to
* embody a specific operation on the "receiver" interface,
* then invoke them on a given concrete implementation.
*
* @see DiffListApplication_test
*/
@ -153,40 +142,33 @@ namespace test{
run (Arg)
{
TokenSeq tokens = build_and_copy_tokens();
render_verbose (tokens);
// profile.append_woof(1, 2);
apply_VerboseRenderer (tokens);
apply_different_receivers (tokens);
verify_copy_and_equality (tokens);
}
/** prepare a sequence of verbs
* for the actual tests to work on */
/* VerbSeq
build_test_feed()
{
return {
VERB_woof,
VERB_honk,
VERB_moo,
VERB_meh
};
}
*/
/** @test verify the correct individual dispatch
* through a computation specific for the given verb
*/
TokenSeq
build_and_copy_tokens ()
{
Token littleWoof(&Receiver::woof, "woof", false, 3u);
Token bigWoof(&Receiver::woof, "woof", true, 2u);
Token quack(&Receiver::honk, "honk", string{"quaack"});
Token honk(&Receiver::honk, "honk", string{"Hoonk"});
Token moo(&Receiver::moo, "moo", Trackr(3));
Token littleWoof(&Receiver::woof, "woof", 0, 3); // NOTE: argument type conversion
Token bigWoof(&Receiver::woof, "woof", true, 2);
Token quack(&Receiver::honk, "honk", "quaack");
Token honk(&Receiver::honk, "honk", "Hoonk");
Token moo(&Receiver::moo, "moo", 3);
Token meh(&Receiver::meh, "meh");
CHECK (sizeof(Token) == sizeof(string) // storage size reserved for the arguments (by declaration of type Token)
+ sizeof(void*) // additional overhead for the VTable for dispatch
+ sizeof(void(Receiver::*)()) // storage for the function pointer to the interface function
+ sizeof(Literal) // storage for the verb symbol (for diagnostics and equality comparisions)
);
return TokenSeq{{littleWoof, quack,honk, bigWoof, moo, meh}};
// add LVal-copies to result sequence
return TokenSeq{{littleWoof, quack, honk, bigWoof, moo, meh}};
}
/** @test demonstrate the dispatching
@ -195,7 +177,7 @@ namespace test{
* the name of the invoked verb
*/
void
render_verbose (TokenSeq& tokens)
apply_VerboseRenderer (TokenSeq& tokens)
{
VerboseRenderer receiver;
for (Token& tok : tokens)
@ -205,6 +187,52 @@ namespace test{
<< "'\n";
}
/** @test demonstrate that another receiver
* indeed invokes different implementations
* of the Interface functions embedded within
* the Verb. Here the implementation just prints
* the name of the invoked verb and the arguments.
*/
void
apply_different_receivers (TokenSeq& tokens)
{
VerboseRenderer verbose;
DiagnosticRenderer diagnostic;
auto render = [&](Receiver& renderer)
{
return join (lib::treeExplore(tokens)
.transform ([&](Token tok)
{
return tok.applyTo (renderer);
})
,"-");
};
CHECK (render(diagnostic) == "woof(false,3)-honk(quaack)-honk(Hoonk)-woof(true,2)-moo(3)-meh()");
CHECK (render(verbose) == "haw-hawhaw-hawhaw-hawhaw-haw-quaack-quaack!-Hoonk-Hoonk!-Woof..Woof..-Moo__Moo__Moo-Meh?");
}
void
verify_copy_and_equality (TokenSeq& tokens)
{
Token bigWoof = tokens[3];
Token oldWoof{&Receiver::woof, "woof", true, 1};
Token oldWolf{&Receiver::woof, "wolf", true, 0};
CHECK (bigWoof == oldWoof);
CHECK (bigWoof != oldWolf);
CHECK (not util::isSameObject (bigWoof, oldWoof));
CHECK (string(bigWoof) == "VerbPack(woof)");
CHECK (string(oldWoof) == "VerbPack(woof)");
CHECK (string(oldWolf) == "VerbPack(wolf)");
VerboseRenderer bark;
CHECK (bigWoof.applyTo(bark) == "Woof..Woof..");
CHECK (oldWoof.applyTo(bark) == "Woof..");
CHECK (oldWolf.applyTo(bark) == "");
}
};

View file

@ -125,8 +125,8 @@ namespace test {
/* == ElementAccess interface == */
RawResult
performAccessTo (UICoord::Builder & target, size_t limitCreation) override
{
performAccessTo (UICoord::Builder & target, size_t) override
{ /////////////////////////////////////////////////TICKET #1134 : use a mock component access scheme here instead of some hardwired responses
UICoord const& location = target.uiCoord();
CHECK (existingPath >= location);

View file

@ -19650,8 +19650,8 @@
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247320686" ID="ID_1896093043" MODIFIED="1557498707228" TEXT="brauche Visitor mit flexiblen Argumenten">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247320686" ID="ID_1896093043" MODIFIED="1557590822696" TEXT="brauche Visitor mit flexiblen Argumenten">
<icon BUILTIN="pencil"/>
<node CREATED="1555247502178" ID="ID_297247554" MODIFIED="1557498707228" TEXT="Anforderung">
<icon BUILTIN="yes"/>
<node CREATED="1555247509182" ID="ID_184476156" MODIFIED="1557498707228" TEXT="funktioniert genauso wie Visitor im Diff, mit Verb-Tokens"/>
@ -19667,15 +19667,19 @@
<node CREATED="1555247665396" ID="ID_1210108422" MODIFIED="1557498707228" TEXT="vermutlich werden Lambdas eine Rolle spielen"/>
<node CREATED="1555247678988" ID="ID_1615700205" MODIFIED="1557498707228" TEXT="aber ich m&#xf6;chte Heap-Storage vermeiden"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247704342" ID="ID_929740643" MODIFIED="1557498707228" TEXT="Entwurf/Test">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247713060" ID="ID_1159666241" MODIFIED="1557498707228" TEXT="proof-of-concept">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1555247704342" ID="ID_929740643" MODIFIED="1557590585181" TEXT="Entwurf/Test">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1555247713060" ID="ID_1159666241" MODIFIED="1557590555065" TEXT="proof-of-concept">
<icon BUILTIN="button_ok"/>
<node CREATED="1555247744121" ID="ID_1280520595" MODIFIED="1557498707228" TEXT="ausgehend von Kopie des VerbToken"/>
<node CREATED="1555247757037" ID="ID_1249615365" MODIFIED="1557498707228" TEXT="(optional) vielleicht letztlich in eine L&#xf6;sung verschmelzen?"/>
<node CREATED="1555247757037" ID="ID_1249615365" MODIFIED="1557590532864" TEXT="(optional) vielleicht letztlich in eine L&#xf6;sung verschmelzen?">
<icon BUILTIN="hourglass"/>
<node CREATED="1557590535366" ID="ID_568258701" MODIFIED="1557590538950" TEXT="vermutlich ehr nicht"/>
<node CREATED="1557590539635" ID="ID_1843674392" MODIFIED="1557590549256" TEXT="da PolymorphicValue doch recht komplex ist"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555806526685" ID="ID_192016641" MODIFIED="1557498707228" TEXT="L&#xf6;sungsansatz: PolymorphicValue">
<icon BUILTIN="pencil"/>
</node>
<node COLOR="#338800" CREATED="1555806526685" ID="ID_192016641" MODIFIED="1557590525234" TEXT="L&#xf6;sungsansatz: PolymorphicValue">
<icon BUILTIN="button_ok"/>
<node CREATED="1555806541914" ID="ID_1260020116" MODIFIED="1557498707228" TEXT="der bietet genau den flexiblen inline-Buffer, den ich hier brauche">
<richcontent TYPE="NOTE"><html>
<head>
@ -19703,8 +19707,8 @@
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555806670026" ID="ID_604641822" MODIFIED="1557498707228" TEXT="Probleme bei der Umsetzung">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1555806670026" ID="ID_604641822" MODIFIED="1557590449417" TEXT="Probleme bei der Umsetzung">
<icon BUILTIN="button_ok"/>
<node CREATED="1555807073875" ID="ID_1971528084" MODIFIED="1557498707228" TEXT="std::apply verwenden">
<icon BUILTIN="stop-sign"/>
<node CREATED="1555807086938" ID="ID_354296634" MODIFIED="1557498707228" TEXT="gitbts noch nicht auf Debian-Stretch"/>
@ -19730,7 +19734,7 @@
</node>
</node>
</node>
<node CREATED="1555806696990" ID="ID_1464210384" MODIFIED="1557498707228" TEXT="kann nicht Tuple-Element per std::forward weitergeben">
<node CREATED="1555806696990" FOLDED="true" ID="ID_1464210384" MODIFIED="1557590459821" TEXT="kann nicht Tuple-Element per std::forward weitergeben">
<icon BUILTIN="button_cancel"/>
<node CREATED="1555806733962" ID="ID_1424612840" MODIFIED="1557498707228" TEXT="Compiler m&#xf6;chte eine RValue-Referenz"/>
<node CREATED="1555806760125" ID="ID_1741677842" MODIFIED="1557498707228" TEXT="workaround: das Tuple selber per std::forward an std::get &#xfc;bergeben">
@ -19945,7 +19949,9 @@
</node>
</node>
</node>
<node CREATED="1555807238238" ID="ID_383098394" MODIFIED="1557498707229" TEXT="Copy-Support von PolymorphicValue ist &quot;komisch&quot;">
<node CREATED="1555807238238" FOLDED="true" ID="ID_383098394" MODIFIED="1557590514367" TEXT="Copy-Support von PolymorphicValue ist &quot;komisch&quot;">
<arrowlink COLOR="#829ebf" DESTINATION="ID_596556632" ENDARROW="Default" ENDINCLINATION="-282;0;" ID="Arrow_ID_1622655110" STARTARROW="None" STARTINCLINATION="-74;193;"/>
<icon BUILTIN="hourglass"/>
<node CREATED="1555807266221" ID="ID_262959695" MODIFIED="1557498707229" TEXT="nach heutigem Stand: unbeholfen implementiert"/>
<node CREATED="1555807285055" ID="ID_1456730365" MODIFIED="1557498707229" TEXT="braucht expliziten Support vom Payload typ"/>
<node CREATED="1555807297726" ID="ID_1905059435" MODIFIED="1557498707229" TEXT="das w&#xe4;re heute gar nicht mehr notwendig"/>
@ -20112,16 +20118,17 @@
<node CREATED="1555807443642" ID="ID_90620144" MODIFIED="1557498707229" TEXT="sollte selbst&#xe4;ndig erkennen, ob der Zieltyp kopierbar ist"/>
<node CREATED="1555807464657" ID="ID_1089528099" MODIFIED="1557498707229" TEXT="diese meta-Intelligenz sollte komplett in dem Adapter stecken"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1557446611550" ID="ID_596556632" MODIFIED="1557498707229" TEXT="Ticket #1197 : rationalise copy support in PolymorphicValue">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1557446611550" ID="ID_596556632" MODIFIED="1557590501784" TEXT="Ticket #1197 : rationalise copy support in PolymorphicValue">
<linktarget COLOR="#1a64bc" DESTINATION="ID_596556632" ENDARROW="Default" ENDINCLINATION="-129;0;" ID="Arrow_ID_884404467" SOURCE="ID_1511870599" STARTARROW="None" STARTINCLINATION="-284;0;"/>
<linktarget COLOR="#829ebf" DESTINATION="ID_596556632" ENDARROW="Default" ENDINCLINATION="-282;0;" ID="Arrow_ID_1622655110" SOURCE="ID_383098394" STARTARROW="None" STARTINCLINATION="-74;193;"/>
<icon BUILTIN="flag-yellow"/>
</node>
</node>
<node CREATED="1555807762543" ID="ID_1645640007" MODIFIED="1557498707229" TEXT="Problem: Puffergr&#xf6;&#xdf;e">
<node CREATED="1555807778751" ID="ID_1563586526" MODIFIED="1557498707229" TEXT="PolymorphicValue verlangt, da&#xdf; man die Puffergr&#xf6;&#xdf;e als Template-Argument definiert"/>
<node CREATED="1555807802562" ID="ID_1845631121" MODIFIED="1557498707229" TEXT="hier h&#xe4;ngt diese aber von der Storage f&#xfc;r die Funktionsargumente ab."/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555807833997" ID="ID_1153160392" MODIFIED="1557498707229" TEXT="Idealfall: das m&#xfc;&#xdf;te automatisch funktionieren">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555807833997" ID="ID_1153160392" MODIFIED="1557590273404" TEXT="Idealfall: das m&#xfc;&#xdf;te automatisch funktionieren">
<icon BUILTIN="button_cancel"/>
<node CREATED="1555807861314" ID="ID_352919826" MODIFIED="1557498707229" TEXT="geht das &#xfc;berhaupt?"/>
<node CREATED="1555807866689" ID="ID_1851833268" MODIFIED="1557498707229" TEXT="w&#xfc;rde vermutlich auf ein Builder-Konstrukt hinauslaufen">
<richcontent TYPE="NOTE"><html>
@ -20156,22 +20163,26 @@
</body>
</html></richcontent>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555807845319" ID="ID_1999765895" MODIFIED="1557498707229" TEXT="Halbe L&#xf6;sung: wenigstens eine Hilfsfunktion bereitstellen">
<icon BUILTIN="flag-yellow"/>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1557590275193" ID="ID_756824768" MODIFIED="1557590280062" TEXT="YAGNI">
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808026434" ID="ID_1634107778" MODIFIED="1557498707229" TEXT="automatische Konversionen f&#xfc;r konkrete Argumente">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1555807845319" ID="ID_1999765895" MODIFIED="1557590260752" TEXT="Halbe L&#xf6;sung: wenigstens eine Hilfsfunktion bereitstellen">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node COLOR="#338800" CREATED="1555808026434" ID="ID_1634107778" MODIFIED="1557590425363" TEXT="automatische Konversionen f&#xfc;r konkrete Argumente">
<icon BUILTIN="button_ok"/>
<node CREATED="1555808055328" ID="ID_1683773555" MODIFIED="1557498707229" TEXT="der VerbPack - Konstruktor sollte sich genau so verhalten wie die Zielfunktion">
<icon BUILTIN="idea"/>
</node>
<node CREATED="1555808100082" ID="ID_1008688397" MODIFIED="1557498707229" TEXT="Beispiel: Zielfunktion nimmt einen std::string, gegeben ist ein C-String-Literal"/>
<node CREATED="1555808124882" ID="ID_364451047" MODIFIED="1557498707229" TEXT="aktuell wird exakt der korrekte Typ erwartet"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808138474" ID="ID_847234596" MODIFIED="1557498707229" TEXT="Grund: Funktionsweise der Teplate-Argument-Inferenz">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1555808138474" ID="ID_847234596" MODIFIED="1557590439076" TEXT="Grund: Funktionsweise der Teplate-Argument-Inferenz">
<icon BUILTIN="info"/>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1555808184873" ID="ID_804931772" MODIFIED="1557498707229" TEXT="sinnvoller Workaround">
<node COLOR="#435e98" CREATED="1555808184873" ID="ID_804931772" MODIFIED="1557590291568" TEXT="sinnvoller Workaround">
<icon BUILTIN="help"/>
<node CREATED="1555808201687" ID="ID_191950649" MODIFIED="1557498707229" TEXT="&quot;Zwiebelschalen-Konstrukt&quot;??">
<richcontent TYPE="NOTE"><html>
@ -20189,15 +20200,70 @@
</html></richcontent>
<icon BUILTIN="idea"/>
</node>
<node CREATED="1557590299574" ID="ID_1634972448" MODIFIED="1557590314138" TEXT="rein zuf&#xe4;llig delegiere ich bereits &#xfc;ber zwei Konstrukturen"/>
<node COLOR="#338800" CREATED="1557590314884" ID="ID_1086686390" MODIFIED="1557590420718" TEXT="also einfach die Argument-Typen vom Funktions-Handler nehmen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
anstatt, wie es die bisherige (naive) implementierung macht,
</p>
<p>
die typename ARGS... auch daf&#252;r zu verwenden, den Handler-Typ zu konstruieren.
</p>
<p>
Mit diesem einfachen Kniff passiert die Konvertierung dann in dem Moment,
</p>
<p>
wo wir die konkreten Argumente in den vorbereiteten Argument-Tupel im Holder schieben
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808280478" ID="ID_59896827" MODIFIED="1557498707229" TEXT="Testabdeckung">
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#338800" CREATED="1555808280478" ID="ID_59896827" MODIFIED="1557590523471" TEXT="Testabdeckung">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1557590726512" ID="ID_1345932776" MODIFIED="1557590812617" TEXT="mehrere verschiedene Receiver">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1557590733137" ID="ID_297834334" MODIFIED="1557590812186" TEXT="Kopier-Verhalten im Detail untersucht">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...jeodch nicht eigens im Test dokumentiert
</p>
<ul>
<li>
weil das sehr aufwendig w&#228;re und den kompletten Test dominieren w&#252;rde
</li>
<li>
weil die Implementierung (in dieser Hinsicht) letztlich banal ist: Anwenden eines Tupel auf eine Funktion
</li>
</ul>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1557590794163" ID="ID_497379433" MODIFIED="1557590811601" TEXT="Werte kopiert und verglichen">
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1557590805129" ID="ID_158433397" MODIFIED="1557590810851" TEXT="ausf&#xfc;hrlich kommentiert">
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808288856" ID="ID_1931717111" MODIFIED="1557498707229" TEXT="Frage: ist das Design gut?">
<icon BUILTIN="flag-yellow"/>
</node>
<node COLOR="#435e98" CREATED="1555808288856" ID="ID_1931717111" MODIFIED="1557590603605" TEXT="Frage: ist das Design gut?">
<icon BUILTIN="button_ok"/>
<node CREATED="1555808300703" ID="ID_621465643" MODIFIED="1557498707229" TEXT="kann/sollte die L&#xf6;song mehr integriert sein?">
<richcontent TYPE="NOTE"><html>
<head>
@ -20210,7 +20276,7 @@
</body>
</html></richcontent>
</node>
<node CREATED="1555808311417" ID="ID_1932269477" MODIFIED="1557498707229" TEXT="oder ist es grade ein Vorteil, wenn sie ein roher Baustein ist">
<node CREATED="1555808311417" ID="ID_1932269477" MODIFIED="1557590690950" TEXT="oder ist es grade ein Vorteil, wenn sie ein roher Baustein ist">
<richcontent TYPE="NOTE"><html>
<head>
@ -20224,9 +20290,38 @@
</p>
</body>
</html></richcontent>
<linktarget COLOR="#fcda04" DESTINATION="ID_1932269477" ENDARROW="Default" ENDINCLINATION="290;0;" ID="Arrow_ID_742389536" SOURCE="ID_128501904" STARTARROW="None" STARTINCLINATION="187;8;"/>
</node>
<node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1557590616683" ID="ID_128501904" MODIFIED="1557590701982" TEXT="ich halte es jetzt f&#xfc;r gelungen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
weil ich es geschafft habe,
</p>
<p>
den gesamten Auswahl-Mechanismus in einen einzigen Konstruktur-Aufruf zu packen.
</p>
<p>
Man kann also nach Belieben VerbPacks in allen Varianten bauen,
</p>
<p>
und es obliegt der n&#228;chst h&#246;heren Schicht, dies auch in sinnvollem Rahmen zu tun...
</p>
</body>
</html>
</richcontent>
<arrowlink COLOR="#fcda04" DESTINATION="ID_1932269477" ENDARROW="Default" ENDINCLINATION="290;0;" ID="Arrow_ID_742389536" STARTARROW="None" STARTINCLINATION="187;8;"/>
<font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="yes"/>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1557590586650" ID="ID_1348312855" MODIFIED="1557590595855" TEXT="den (neu gebauten) VerbPack integrieren">
<icon BUILTIN="flag-yellow"/>
</node>
</node>
</node>
</node>