Library: RandomDraw - must accept generic arguments
...since the Policy class now defines the function signature, we can no longer assume that "input" is size_t. Rather, all invocations must rely on the generic adaptaion scheme. Getting this correct turns out rather tricky again; best to rely on a generic function-composition. Indeed I programmed such a helper several years ago, with the caveat that at that time we used C++03 and could not perfect-forward arguments. Today this problem can be solved much more succinct using generic Lambdas.
This commit is contained in:
parent
651e28bac9
commit
75dd4210f2
5 changed files with 221 additions and 200 deletions
|
|
@ -644,123 +644,6 @@ namespace func{
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace _composed { // repetitive impl.code for function composition
|
||||
using std::bind;
|
||||
using std::function;
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
using std::placeholders::_3;
|
||||
using std::placeholders::_4;
|
||||
using std::placeholders::_5;
|
||||
using std::placeholders::_6;
|
||||
using std::placeholders::_7;
|
||||
using std::placeholders::_8;
|
||||
using std::placeholders::_9;
|
||||
|
||||
template<typename RES, typename F1, typename F2, uint n>
|
||||
struct Build;
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 0 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 1 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 2 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 3 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 4 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 5 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 6 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 7 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 8 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8)); }
|
||||
};
|
||||
|
||||
template<typename RES, typename F1, typename F2>
|
||||
struct Build<RES,F1,F2, 9 >
|
||||
{
|
||||
static function<RES> func(F1& f1, F2& f2) { return bind (f2, bind (f1,_1,_2,_3,_4,_5,_6,_7,_8,_9)); }
|
||||
};
|
||||
} // (End) impl namespace (_composed)
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Functional composition. Create a functor, which
|
||||
* on invocation will execute two functions chained,
|
||||
* i.e. fed the result of invoking the first function
|
||||
* as argument into the second function.
|
||||
*/
|
||||
template<typename F1, typename RET>
|
||||
class FunctionComposition
|
||||
{
|
||||
typedef typename _Fun<F1>::Args Args;
|
||||
typedef typename _Fun<F1>::Ret Ret1;
|
||||
|
||||
typedef Types<Ret1> ArgsF2;
|
||||
typedef typename FunctionTypedef<RET, ArgsF2>::Sig SigF2;
|
||||
typedef typename FunctionTypedef<RET, Args>::Sig ChainedSig;
|
||||
|
||||
enum { ARG_CNT = count<typename Args::List>::value };
|
||||
|
||||
|
||||
public:
|
||||
static function<ChainedSig>
|
||||
chain (F1& f1, SigF2& f2)
|
||||
{
|
||||
return _composed::Build<ChainedSig,F1,SigF2, ARG_CNT>::func (f1,f2);
|
||||
}
|
||||
static function<ChainedSig>
|
||||
chain (F1& f1, function<SigF2>& f2)
|
||||
{
|
||||
return _composed::Build<ChainedSig,F1,function<SigF2>, ARG_CNT>::func (f1,f2);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Bind a specific argument to an arbitrary value.
|
||||
* Especially, this "value" might be another binder.
|
||||
|
|
@ -826,13 +709,13 @@ namespace func{
|
|||
typedef FunctionClosure<Signature> Type;
|
||||
};
|
||||
|
||||
template<typename SIG1, typename SIG2>
|
||||
template<typename FUN1, typename FUN2>
|
||||
struct _Chain
|
||||
{
|
||||
typedef typename _Fun<SIG1>::Args Args;
|
||||
typedef typename _Fun<SIG2>::Ret Ret;
|
||||
typedef typename FunctionTypedef<Ret, Args>::Sig Chained;
|
||||
typedef function<Chained> Function;
|
||||
typedef typename _Fun<FUN1>::Args Args;
|
||||
typedef typename _Fun<FUN2>::Ret Ret;
|
||||
typedef typename FunctionTypedef<Ret, Args>::Sig ChainedSig;
|
||||
typedef function<ChainedSig> Functor;
|
||||
};
|
||||
|
||||
template<typename SIG>
|
||||
|
|
@ -946,14 +829,21 @@ namespace func{
|
|||
}
|
||||
|
||||
|
||||
/** build a functor chaining the given functions */
|
||||
template<typename SIG1, typename SIG2>
|
||||
inline
|
||||
typename _Chain<SIG1,SIG2>::Function
|
||||
chained (SIG1& f1, SIG2& f2)
|
||||
/** build a functor chaining the given functions: feed the result of f1 into f2.
|
||||
* @note the mathematical notation would be `chained ≔ f2 ∘f1`
|
||||
*/
|
||||
template<typename FUN1, typename FUN2>
|
||||
inline auto
|
||||
chained (FUN1&& f1, FUN2&& f2)
|
||||
{
|
||||
typedef typename _Chain<SIG1,SIG2>::Ret Ret;
|
||||
return FunctionComposition<SIG1,Ret>::chain (f1, f2);
|
||||
using Ret = typename _Chain<FUN1,FUN2>::Ret;
|
||||
|
||||
return [functor1 = std::forward<FUN1> (f1)
|
||||
,functor2 = std::forward<FUN2> (f2)]
|
||||
(auto&& ...args) -> Ret
|
||||
{
|
||||
return functor2 (functor1 (std::forward<decltype(args)> (args)...));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/meta/function-closure.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
|
@ -138,10 +139,11 @@ namespace lib {
|
|||
if (probability_ == 0.0 or val == 0.0)
|
||||
return Tar{0};
|
||||
double q = (1.0 - probability_);
|
||||
auto org = Tar::minVal();
|
||||
val -= q; // [0 .. [q .. 1[
|
||||
val /= probability_; // [0 .. 1[
|
||||
val *= maxResult_; // [0 .. m[
|
||||
val += 1; // [1 .. m]
|
||||
val *= maxResult_ - org; // [0 .. m[
|
||||
val += org+1; // [1 .. m]
|
||||
val += CAP_EPSILON; // round down yet absorb dust
|
||||
return Tar{val};
|
||||
}
|
||||
|
|
@ -156,6 +158,13 @@ namespace lib {
|
|||
return double(hash % QUANTISER) / QUANTISER;
|
||||
}
|
||||
|
||||
/** @internal core operation: draw and quantise into limited value */
|
||||
Tar
|
||||
drawLimited (size_t hash)
|
||||
{
|
||||
return limited (asRand (hash));
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
/** Drawing is _disabled_ by default, always yielding "zero" */
|
||||
|
|
@ -190,7 +199,7 @@ namespace lib {
|
|||
}
|
||||
|
||||
RandomDraw&&
|
||||
maxVal (uint m)
|
||||
maxVal (Tar m)
|
||||
{
|
||||
maxResult_ = m;
|
||||
return move (*this);
|
||||
|
|
@ -228,33 +237,25 @@ namespace lib {
|
|||
static_assert (lib::meta::_Fun<FUN>(), "Need something function-like.");
|
||||
|
||||
using Res = typename lib::meta::_Fun<FUN>::Ret;
|
||||
using lib::meta::func::chained;
|
||||
|
||||
if constexpr (std::is_same_v<Res, Tar>)
|
||||
if constexpr (std::is_same_v<Res, Tar>)// ◁──────────────────────────┨ function produces result directly
|
||||
return std::forward<FUN>(fun);
|
||||
else
|
||||
if constexpr (std::is_same_v<Res, size_t>)
|
||||
return [functor=std::forward<FUN>(fun), this]
|
||||
(size_t rawHash)
|
||||
{
|
||||
size_t hash = functor(rawHash);
|
||||
double randomNum = asRand (hash);
|
||||
return limited (randomNum);
|
||||
};
|
||||
if constexpr (std::is_same_v<Res, size_t>)// ◁───────────────────────┨ function yields random source to draw value
|
||||
return chained (std::forward<FUN>(fun)
|
||||
,[this](size_t hash){ return drawLimited(hash); });
|
||||
else
|
||||
if constexpr (std::is_same_v<Res, double>)
|
||||
return [functor=std::forward<FUN>(fun), this]
|
||||
(size_t rawHash)
|
||||
{
|
||||
double randomNum = functor(rawHash);
|
||||
return limited (randomNum);
|
||||
};
|
||||
if constexpr (std::is_same_v<Res, double>)// ◁───────────────────────┨ function yields random value to be quantised
|
||||
return chained (std::forward<FUN>(fun)
|
||||
,[this](double rand){ return limited(rand); });
|
||||
else
|
||||
if constexpr (std::is_same_v<Res, RandomDraw>)
|
||||
if constexpr (std::is_same_v<Res, RandomDraw>)// ◁────────────────────┨ function yields parametrised RandomDraw to invoke
|
||||
return [functor=std::forward<FUN>(fun), this]
|
||||
(size_t rawHash)
|
||||
{
|
||||
RandomDraw parametricDraw = functor(rawHash);
|
||||
return parametricDraw (rawHash);
|
||||
(auto&& ...inArgs)
|
||||
{ // invoke with copy
|
||||
RandomDraw parametricDraw = functor(inArgs...);
|
||||
return parametricDraw (forward<decltype(inArgs)> (inArgs)...);
|
||||
};
|
||||
else
|
||||
static_assert (not sizeof(Res), "unable to adapt / handle result type");
|
||||
|
|
|
|||
|
|
@ -396,18 +396,16 @@ namespace wrapper {
|
|||
|
||||
|
||||
/**
|
||||
* Extension of ItemWrapper: a function remembering
|
||||
* the result of the last invocation. Initially, the "value"
|
||||
* is bottom (undefined, NIL), until the function is invoked
|
||||
* for the first time. After that, the result of the last
|
||||
* invocation can be accessed by `operator* ()`
|
||||
*
|
||||
* @note non-copyable. (removing this limitation would
|
||||
* require a much more expensive implementation,
|
||||
* by implementing operator() ourselves)
|
||||
* Extension of ItemWrapper: a function remembering the result of the
|
||||
* last invocation. Initially, the "value" is bottom (undefined, NIL),
|
||||
* until the function is invoked for the first time. After that, the
|
||||
* result of the last invocation can be accessed by `operator* ()`
|
||||
* @note deliberately non-copyable, since we capture a reference
|
||||
* to `this` in order to write to the embedded ItemWrapper.
|
||||
* (to alleviate, we'd have to re-link after copying/moving)
|
||||
*/
|
||||
template<typename SIG>
|
||||
class FunctionResult
|
||||
struct FunctionResult
|
||||
: public function<SIG>
|
||||
, util::NonCopyable
|
||||
{
|
||||
|
|
@ -416,43 +414,28 @@ namespace wrapper {
|
|||
|
||||
ResWrapper lastResult_;
|
||||
|
||||
|
||||
Res
|
||||
captureResult (Res res)
|
||||
{
|
||||
lastResult_ = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
public:
|
||||
/** default ctor yields an object
|
||||
* locked to \em invalid state */
|
||||
FunctionResult () { }
|
||||
/** by default locked to _invalid state_ */
|
||||
FunctionResult() = default;
|
||||
|
||||
/** Create result-remembering functor
|
||||
* by binding the given function. Explanation:
|
||||
* - `*this` is a _function_
|
||||
* - initially it is defined as invalid
|
||||
* - then we build the function composition of
|
||||
* the target function, and a function storing
|
||||
* the result value into the ResWrapper member
|
||||
* - define ourselves by assigning the resulting
|
||||
* composite function
|
||||
/**
|
||||
* Create result-remembering functor by outfitting a _copy_
|
||||
* of the given function with an adaptor to _capture_ each
|
||||
* produced result.
|
||||
* @warning if function result is a value, it is copied.
|
||||
*/
|
||||
template<typename FUN>
|
||||
FunctionResult (FUN targetFunction)
|
||||
{
|
||||
using std::bind;
|
||||
using std::placeholders::_1;
|
||||
using lib::meta::func::chained;
|
||||
// note: binding "this" mandates noncopyable
|
||||
function<Res(Res)> doCaptureResult = bind (&FunctionResult::captureResult, this, _1 );
|
||||
function<SIG> chainedWithResCapture = chained (targetFunction, doCaptureResult);
|
||||
|
||||
function<SIG>::operator= (chainedWithResCapture); // define the function (baseclass)
|
||||
}
|
||||
|
||||
FunctionResult (FUN&& targetFunction)
|
||||
: function<SIG>{lib::meta::func::chained
|
||||
( std::forward<FUN> (targetFunction)
|
||||
, [this](Res res) -> Res
|
||||
{
|
||||
lastResult_ = res;
|
||||
return std::forward<Res> (res);
|
||||
})}
|
||||
{ }
|
||||
|
||||
/** retrieve the last function result observed */
|
||||
Res& operator*() const { return *lastResult_; }
|
||||
bool isValid () const { return lastResult_.isValid(); }
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "lib/test/run.hpp"
|
||||
//#include "lib/test/test-helper.hpp"
|
||||
#include "lib/random-draw.hpp"
|
||||
#include "lib/time/timevalue.hpp"
|
||||
#include "lib/test/diagnostic-output.hpp"////////////////////TODO
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
|
|
@ -42,6 +43,8 @@ namespace test{
|
|||
|
||||
// using util::isSameObject;
|
||||
// using std::rand;
|
||||
using lib::time::FSecs;
|
||||
using lib::time::TimeVar;
|
||||
|
||||
// namespace error = lumiera::error;
|
||||
// using error::LUMIERA_ERROR_FATAL;
|
||||
|
|
@ -154,8 +157,21 @@ SHOW_EXPR (int(draw(256)));
|
|||
void
|
||||
verify_policy()
|
||||
{
|
||||
// auto d1 = RandomDraw<random_draw::LimitedRandomGenerate<5>>().probability(1.0);
|
||||
//SHOW_EXPR (uint(d1()))
|
||||
auto d1 = RandomDraw<random_draw::LimitedRandomGenerate<5>>().probability(1.0);
|
||||
uint v1 = d1();
|
||||
CHECK (0 < v1 and v1 <=5);
|
||||
|
||||
struct SpecialPolicy
|
||||
: function<Limited<char, 'Z','A'>(char,uint)>
|
||||
{
|
||||
static double defaultSrc (char b, uint off) { return fmod ((b-'A'+off)/double('Z'-'A'), 1.0); }
|
||||
};
|
||||
|
||||
auto d2 = RandomDraw<SpecialPolicy>().probability(1.0);
|
||||
CHECK (d2('A', 2) == 'D');
|
||||
CHECK (d2('M',10) == 'X');
|
||||
CHECK (d2('Y', 0) == 'Z');
|
||||
CHECK (d2('Y',15) == 'P');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -96642,10 +96642,82 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1700515519514" ID="ID_1957414628" MODIFIED="1700515559845" TEXT="⟹ dann müßte aber die Policy einen Default-Eingang liefern..."/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700515561328" ID="ID_408143188" MODIFIED="1700515586492" TEXT="brauche Funktions-Komposition">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node CREATED="1700515591564" ID="ID_9942626" MODIFIED="1700515612341" TEXT="»beliebige Funktion« kann nicht als Lambda geschrieben werden"/>
|
||||
<node BACKGROUND_COLOR="#f0d5c5" COLOR="#990033" CREATED="1700515624424" ID="ID_124826134" MODIFIED="1700515633951" TEXT="hatte ich da nicht schon mal was...?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node COLOR="#435e98" CREATED="1700515591564" ID="ID_9942626" MODIFIED="1700536064914" TEXT="»beliebige Funktion« kann nicht einfach so als Lambda geschrieben werden">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1700515624424" ID="ID_124826134" MODIFIED="1700535846007" TEXT="hatte ich da nicht schon mal was...?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1700535702492" ID="ID_1908131428" MODIFIED="1700535708739" TEXT="function-composition.hpp"/>
|
||||
<node CREATED="1700535710200" ID="ID_1837337426" MODIFIED="1700535728417" TEXT="ja mei... da hab ich mich damals aber geplagt..."/>
|
||||
<node CREATED="1700535729775" ID="ID_1473128844" MODIFIED="1700535747481" TEXT="und obendrein wird da überall noch unterwegs kopiert"/>
|
||||
<node CREATED="1700535573341" ID="ID_853243392" MODIFIED="1700536001123">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
geht heutzutage <i>relativ kompakt </i>mit generischen Lambdas
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
...ich hab nicht „lesbar“ gesagt...
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<arrowlink COLOR="#7d8ebd" DESTINATION="ID_1908683822" ENDARROW="Default" ENDINCLINATION="-700;170;" ID="Arrow_ID_268440367" STARTARROW="None" STARTINCLINATION="-2105;102;"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#520f69" CREATED="1700535778319" ID="ID_1551608043" MODIFIED="1700535833317" TEXT="(...wenn man's denn auch richtig macht..)">
|
||||
<font NAME="SansSerif" SIZE="11"/>
|
||||
<icon BUILTIN="smiley-angry"/>
|
||||
<node COLOR="#435e98" CREATED="1700535872361" ID="ID_1665961777" MODIFIED="1700535896456" TEXT="ich sage bloß: Referenzen als Rückgabewert...">
|
||||
<font NAME="SansSerif" SIZE="8"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#c8c0b6" COLOR="#435e98" CREATED="1700535872361" ID="ID_1926879979" MODIFIED="1700535933707" TEXT="...und das RECHTFERTIGT eine Library-Funktion">
|
||||
<font NAME="SansSerif" SIZE="9"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700535940171" ID="ID_80963960" MODIFIED="1700535962800" TEXT="lib::meta::func::chained() modernisiert">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700542206019" ID="ID_1976162819" MODIFIED="1700542219117" TEXT="damit adaptOut umformulieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700542247014" ID="ID_185624626" MODIFIED="1700542286224" TEXT="die »gesamt-Kette« als drawLimited() ≡ limited (asRand (hash));">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1700542287784" ID="ID_438421800" MODIFIED="1700542320316" TEXT="der »parametrised Draw« ist komplex">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1700542321812" ID="ID_1608379732" MODIFIED="1700542336725">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
muß die Funktionsargumente <b>kopieren</b>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700542337681" ID="ID_1192170625" MODIFIED="1700542352927" TEXT="also in dem Fall dann doch ausschreiben">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700542362630" ID="ID_730331755" MODIFIED="1700542375501" TEXT="mit speziellem Test ausleuchten...">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1700542382819" ID="ID_1832228113" MODIFIED="1700542395074" TEXT="eine Policy die zwei Eingangs-Argumente nimmt"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -103542,6 +103614,65 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1700523608170" ID="ID_1908683822" MODIFIED="1700535684359" TEXT="auch möglich mit generischen λ">
|
||||
<linktarget COLOR="#7d8ebd" DESTINATION="ID_1908683822" ENDARROW="Default" ENDINCLINATION="-700;170;" ID="Arrow_ID_268440367" SOURCE="ID_853243392" STARTARROW="None" STARTINCLINATION="-2105;102;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1700523633130" ID="ID_139668487" MODIFIED="1700523644209" TEXT="decltype mit pack-expansion kombinieren"/>
|
||||
<node CREATED="1700534903724" ID="ID_1622776918" MODIFIED="1700535389459">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
[](auto&& ...<font color="#6e2237">args</font><font color="#000000">) -> RetType </font>{ return fun (forward<<font color="#5d19b8"><b>decltype(</b></font><font color="#6e2237">args</font><font color="#5d19b8"><b>)</b></font>> (<font color="#6e2237">args</font>) <b><font color="#c50101">...</font></b>); }
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1700535233362" ID="ID_767885543" MODIFIED="1700535264581" TEXT="Warnung: bei solchen λ muß man oft den Return-Typ explizit deklarieren">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1700535294817" ID="ID_1372454543" MODIFIED="1700535550594">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
weil bei normaler Typinferenz ein <i>decay </i>stattfindet
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
„zum Beispiel...“ wenn die im Lamba verwendete Funktion eine Referenz zurückliefert, dann passiert ein decay auf den unterliegenden Objekttyp, d.h. man erzeugt eine schwebende Kopie....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node CREATED="1700535322845" ID="ID_1105790015" MODIFIED="1700535376993" TEXT="kann ziemlich heimtückisch sein...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
hab mich grad geschnitten und 5 Stunden nach der Ursache gesucht
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="smiley-oh"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1622386272743" ID="ID_1645901699" MODIFIED="1622386277362" TEXT="I/O">
|
||||
<node CREATED="1622386278646" ID="ID_359102162" MODIFIED="1622386285472" TEXT="sehr große Dateien">
|
||||
|
|
|
|||
Loading…
Reference in a new issue