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 * 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()`. * `iterNext()`, it needs to perform a similar action for `expandChildren()`.
* - it must be behave like a default-constructible, copyable value object * - 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> template<template<class> class LAY>
auto auto

View file

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

View file

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

View file

@ -111,18 +111,28 @@ namespace lib {
} }
/** Building block: the Interface to cause the invocation */
template<class REC, class RET> template<class REC, class RET>
struct VerbInvoker struct VerbInvoker
: polyvalue::CloneValueSupport<polyvalue::EmptyBase> // mark and mix-in virtual copy construction support : polyvalue::CloneValueSupport<polyvalue::EmptyBase> // mark and mix-in virtual copy construction support
{ {
virtual ~VerbInvoker() { } 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> template<class REC, class SIG>
struct VerbHolder; 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> template<class REC, class RET, typename... ARGS>
struct VerbHolder<REC, RET(ARGS...)> struct VerbHolder<REC, RET(ARGS...)>
: VerbInvoker<REC,RET> : VerbInvoker<REC,RET>
@ -134,13 +144,21 @@ namespace lib {
/** meta-sequence to pick argument values from the storage tuple */ /** meta-sequence to pick argument values from the storage tuple */
using SequenceIterator = typename meta::BuildIdxIter<ARGS...>::Ascending; using SequenceIterator = typename meta::BuildIdxIter<ARGS...>::Ascending;
/** Storage for the argument tuple */
Args args_; 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} : Verb{handlerRef, verbID}
, args_{std::forward<ARGS> (args)...} , args_{std::forward<PARS> (args)...}
{ } { }
Literal
getID() const override
{
return Verb::getID();
}
RET RET
applyTo (REC& receiver) override applyTo (REC& receiver) override
{ {
@ -148,45 +166,88 @@ namespace lib {
} }
private: private:
/** @internal actual function invocation, thereby unpacking the argument tuple */
template<size_t...idx> template<size_t...idx>
RET RET
invokeVerb (REC& receiver, meta::IndexSeq<idx...>) 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> template<class REC, class RET, size_t arg_storage>
class VerbPack class VerbPack
: public PolymorphicValue<VerbInvoker<REC,RET>, storageOverhead(arg_storage)> : 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> 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: public:
template<typename...ARGS> /** setup a VerbPack for a given operation on the interface `REC`
VerbPack (Handler<ARGS...> handler, Literal verbID, ARGS&&... args) * @param handler function member-pointer to define the operation
: PolyHolder(PayloadType<ARGS...>(), handler, verbID, std::forward<ARGS>(args)...) * @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 RET
applyTo (REC& receiver) applyTo (REC& receiver)
{ {
VerbInvoker<REC,RET>& dispatch(*this); return PolyHolder::getPayload().applyTo (receiver);
return dispatch.applyTo (receiver); }
operator string() const
{
return "VerbPack("
+ string{util::unConst(this)->getPayload().getID()}
+ ")";
} }
}; };
} // namespace lib
} // namespace lib
#endif /*LIB_VERB_VISITOR_H*/ #endif /*LIB_VERB_VISITOR_H*/

View file

@ -740,6 +740,17 @@ return: 0
END 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 TEST "VectorTransfer_test" VectorTransfer_test <<END
return: 0 return: 0
END END

View file

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

View file

@ -31,118 +31,107 @@
#include "lib/format-string.hpp" #include "lib/format-string.hpp"
#include "lib/format-cout.hpp" #include "lib/format-cout.hpp"
#include "lib/format-util.hpp" #include "lib/format-util.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/iter-tree-explorer.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
#include <tuple>
using std::string; using std::string;
using util::_Fmt; using util::_Fmt;
using util::join; using util::join;
using std::vector; using std::vector;
using std::forward;
using std::make_tuple;
namespace lib { namespace lib {
namespace test{ 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
class Receiver
{ /** the "visitor" interface used by all VerbPacks in this test */
public: class Receiver
virtual ~Receiver() { } ///< this is an interface {
public:
virtual string woof (bool huge, uint cnt) =0; virtual ~Receiver() { } ///< this is an interface
virtual string honk (string) =0;
virtual string moo (Trackr num) =0; virtual string woof (bool huge, uint cnt) =0;
virtual string meh () =0; virtual string honk (string) =0;
}; virtual string moo (size_t 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>; using TokenSeq = vector<Token>;
}
/**
/** * a concrete receiver of verb-tokens,
* a receiver of verb-tokens, * which renders them verbosely
* which renders them verbosely */
*/ class VerboseRenderer
class VerboseRenderer : public Receiver
: public Receiver {
{ string
string woof (bool huge, uint cnt) override
woof (bool huge, uint cnt) override {
{ string woof;
string woof{huge? "Woof..":"haw-haw"}; while (0 < cnt--)
while (0 < cnt--) woof += isnil(woof)? string {huge? "Woof..":"haw-haw"}
woof += woof; : woof;
return woof; return woof;
} }
string string
honk (string theHonk) override honk (string theHonk) override
{ {
return theHonk+"-"+theHonk+"!"; return theHonk+"-"+theHonk+"!";
} }
string string
moo (Trackr num) override moo (size_t num) override
{ {
return join (vector<string>{num.num, "Moo"}, "__"); return join (vector<string>{num, "Moo"}, "__");
} }
string string
meh() override meh() override
{ {
return "Meh!"; 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 * @test Demonstration/Concept: build pre-bound VerbPack objects to
* based on the given verbs of an embedded custom language. * embody a specific operation on the "receiver" interface,
* Actually what we want to achieve here is a specific form * then invoke them on a given concrete implementation.
* of double dispatch; thus the implementation relies on a
* variation of the visitor pattern.
* *
* @see DiffListApplication_test * @see DiffListApplication_test
*/ */
@ -153,40 +142,33 @@ namespace test{
run (Arg) run (Arg)
{ {
TokenSeq tokens = build_and_copy_tokens(); TokenSeq tokens = build_and_copy_tokens();
render_verbose (tokens); apply_VerboseRenderer (tokens);
// profile.append_woof(1, 2); 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 /** @test verify the correct individual dispatch
* through a computation specific for the given verb * through a computation specific for the given verb
*/ */
TokenSeq TokenSeq
build_and_copy_tokens () build_and_copy_tokens ()
{ {
Token littleWoof(&Receiver::woof, "woof", false, 3u); Token littleWoof(&Receiver::woof, "woof", 0, 3); // NOTE: argument type conversion
Token bigWoof(&Receiver::woof, "woof", true, 2u); Token bigWoof(&Receiver::woof, "woof", true, 2);
Token quack(&Receiver::honk, "honk", string{"quaack"}); Token quack(&Receiver::honk, "honk", "quaack");
Token honk(&Receiver::honk, "honk", string{"Hoonk"}); Token honk(&Receiver::honk, "honk", "Hoonk");
Token moo(&Receiver::moo, "moo", Trackr(3)); Token moo(&Receiver::moo, "moo", 3);
Token meh(&Receiver::meh, "meh"); 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 /** @test demonstrate the dispatching
@ -195,7 +177,7 @@ namespace test{
* the name of the invoked verb * the name of the invoked verb
*/ */
void void
render_verbose (TokenSeq& tokens) apply_VerboseRenderer (TokenSeq& tokens)
{ {
VerboseRenderer receiver; VerboseRenderer receiver;
for (Token& tok : tokens) for (Token& tok : tokens)
@ -205,6 +187,52 @@ namespace test{
<< "'\n"; << "'\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 == */ /* == ElementAccess interface == */
RawResult 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(); UICoord const& location = target.uiCoord();
CHECK (existingPath >= location); CHECK (existingPath >= location);

View file

@ -19650,8 +19650,8 @@
</html></richcontent> </html></richcontent>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247320686" ID="ID_1896093043" MODIFIED="1557498707228" TEXT="brauche Visitor mit flexiblen Argumenten"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247320686" ID="ID_1896093043" MODIFIED="1557590822696" TEXT="brauche Visitor mit flexiblen Argumenten">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="pencil"/>
<node CREATED="1555247502178" ID="ID_297247554" MODIFIED="1557498707228" TEXT="Anforderung"> <node CREATED="1555247502178" ID="ID_297247554" MODIFIED="1557498707228" TEXT="Anforderung">
<icon BUILTIN="yes"/> <icon BUILTIN="yes"/>
<node CREATED="1555247509182" ID="ID_184476156" MODIFIED="1557498707228" TEXT="funktioniert genauso wie Visitor im Diff, mit Verb-Tokens"/> <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="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 CREATED="1555247678988" ID="ID_1615700205" MODIFIED="1557498707228" TEXT="aber ich m&#xf6;chte Heap-Storage vermeiden"/>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247704342" ID="ID_929740643" MODIFIED="1557498707228" TEXT="Entwurf/Test"> <node COLOR="#338800" CREATED="1555247704342" ID="ID_929740643" MODIFIED="1557590585181" TEXT="Entwurf/Test">
<icon BUILTIN="pencil"/> <icon BUILTIN="button_ok"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555247713060" ID="ID_1159666241" MODIFIED="1557498707228" TEXT="proof-of-concept"> <node COLOR="#435e98" CREATED="1555247713060" ID="ID_1159666241" MODIFIED="1557590555065" TEXT="proof-of-concept">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
<node CREATED="1555247744121" ID="ID_1280520595" MODIFIED="1557498707228" TEXT="ausgehend von Kopie des VerbToken"/> <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>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555806526685" ID="ID_192016641" MODIFIED="1557498707228" TEXT="L&#xf6;sungsansatz: PolymorphicValue"> </node>
<icon BUILTIN="pencil"/> <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"> <node CREATED="1555806541914" ID="ID_1260020116" MODIFIED="1557498707228" TEXT="der bietet genau den flexiblen inline-Buffer, den ich hier brauche">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -19703,8 +19707,8 @@
</body> </body>
</html></richcontent> </html></richcontent>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555806670026" ID="ID_604641822" MODIFIED="1557498707228" TEXT="Probleme bei der Umsetzung"> <node COLOR="#338800" CREATED="1555806670026" ID="ID_604641822" MODIFIED="1557590449417" TEXT="Probleme bei der Umsetzung">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_ok"/>
<node CREATED="1555807073875" ID="ID_1971528084" MODIFIED="1557498707228" TEXT="std::apply verwenden"> <node CREATED="1555807073875" ID="ID_1971528084" MODIFIED="1557498707228" TEXT="std::apply verwenden">
<icon BUILTIN="stop-sign"/> <icon BUILTIN="stop-sign"/>
<node CREATED="1555807086938" ID="ID_354296634" MODIFIED="1557498707228" TEXT="gitbts noch nicht auf Debian-Stretch"/> <node CREATED="1555807086938" ID="ID_354296634" MODIFIED="1557498707228" TEXT="gitbts noch nicht auf Debian-Stretch"/>
@ -19730,7 +19734,7 @@
</node> </node>
</node> </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"/> <icon BUILTIN="button_cancel"/>
<node CREATED="1555806733962" ID="ID_1424612840" MODIFIED="1557498707228" TEXT="Compiler m&#xf6;chte eine RValue-Referenz"/> <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"> <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>
</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="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="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"/> <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="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 CREATED="1555807464657" ID="ID_1089528099" MODIFIED="1557498707229" TEXT="diese meta-Intelligenz sollte komplett in dem Adapter stecken"/>
</node> </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="#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"/> <icon BUILTIN="flag-yellow"/>
</node> </node>
</node> </node>
<node CREATED="1555807762543" ID="ID_1645640007" MODIFIED="1557498707229" TEXT="Problem: Puffergr&#xf6;&#xdf;e"> <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="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 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"> <node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555807833997" ID="ID_1153160392" MODIFIED="1557590273404" TEXT="Idealfall: das m&#xfc;&#xdf;te automatisch funktionieren">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="button_cancel"/>
<node CREATED="1555807861314" ID="ID_352919826" MODIFIED="1557498707229" TEXT="geht das &#xfc;berhaupt?"/> <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"> <node CREATED="1555807866689" ID="ID_1851833268" MODIFIED="1557498707229" TEXT="w&#xfc;rde vermutlich auf ein Builder-Konstrukt hinauslaufen">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
@ -20156,22 +20163,26 @@
</body> </body>
</html></richcontent> </html></richcontent>
</node> </node>
</node> <node BACKGROUND_COLOR="#ccb59b" COLOR="#6e2a38" CREATED="1557590275193" ID="ID_756824768" MODIFIED="1557590280062" TEXT="YAGNI">
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555807845319" ID="ID_1999765895" MODIFIED="1557498707229" TEXT="Halbe L&#xf6;sung: wenigstens eine Hilfsfunktion bereitstellen"> <font ITALIC="true" NAME="SansSerif" SIZE="14"/>
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="yes"/>
</node> </node>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808026434" ID="ID_1634107778" MODIFIED="1557498707229" TEXT="automatische Konversionen f&#xfc;r konkrete Argumente"> <node COLOR="#338800" CREATED="1555807845319" ID="ID_1999765895" MODIFIED="1557590260752" TEXT="Halbe L&#xf6;sung: wenigstens eine Hilfsfunktion bereitstellen">
<icon BUILTIN="flag-yellow"/> <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"> <node CREATED="1555808055328" ID="ID_1683773555" MODIFIED="1557498707229" TEXT="der VerbPack - Konstruktor sollte sich genau so verhalten wie die Zielfunktion">
<icon BUILTIN="idea"/> <icon BUILTIN="idea"/>
</node> </node>
<node CREATED="1555808100082" ID="ID_1008688397" MODIFIED="1557498707229" TEXT="Beispiel: Zielfunktion nimmt einen std::string, gegeben ist ein C-String-Literal"/> <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 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"> <node CREATED="1555808138474" ID="ID_847234596" MODIFIED="1557590439076" TEXT="Grund: Funktionsweise der Teplate-Argument-Inferenz">
<icon BUILTIN="flag-yellow"/> <icon BUILTIN="info"/>
</node> </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"/> <icon BUILTIN="help"/>
<node CREATED="1555808201687" ID="ID_191950649" MODIFIED="1557498707229" TEXT="&quot;Zwiebelschalen-Konstrukt&quot;??"> <node CREATED="1555808201687" ID="ID_191950649" MODIFIED="1557498707229" TEXT="&quot;Zwiebelschalen-Konstrukt&quot;??">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
@ -20189,15 +20200,70 @@
</html></richcontent> </html></richcontent>
<icon BUILTIN="idea"/> <icon BUILTIN="idea"/>
</node> </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>
</node> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808280478" ID="ID_59896827" MODIFIED="1557498707229" TEXT="Testabdeckung"> </node>
<icon BUILTIN="flag-yellow"/> <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> </node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1555808288856" ID="ID_1931717111" MODIFIED="1557498707229" TEXT="Frage: ist das Design gut?"> </node>
<icon BUILTIN="flag-yellow"/> <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?"> <node CREATED="1555808300703" ID="ID_621465643" MODIFIED="1557498707229" TEXT="kann/sollte die L&#xf6;song mehr integriert sein?">
<richcontent TYPE="NOTE"><html> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -20210,7 +20276,7 @@
</body> </body>
</html></richcontent> </html></richcontent>
</node> </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> <richcontent TYPE="NOTE"><html>
<head> <head>
@ -20224,9 +20290,38 @@
</p> </p>
</body> </body>
</html></richcontent> </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>
</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> </node>
</node> </node>