Library: extend implementation to support references

With this minor change, the internal result-tuple may now also hold references,
in case a source iterator exposes a reference (which is in fact the standard case).

Under the right circumstances, source-manipulation through the iterator becomes possible.
Moreover, the optimiser should now be able to elide the result-value tuple in many cases.
and access the iterator internals directly instead.

Obviously this is an advanced and possibly dangerous feature, and only possible
when no additional transformer functions are interspersed; moreover this prompted
a review of some long standing type definitions to more precisely reflect the intention.

Note: most deliberately, the Transformer element in IterExplorer must expose a reference type,
and capture the results into an internal ItemWrapper. This is the only way we can support arbitrary functions.
This commit is contained in:
Fischlurch 2024-11-22 23:54:57 +01:00
parent f0eeabb29e
commit 0b487735c2
9 changed files with 334 additions and 108 deletions

View file

@ -429,10 +429,10 @@ namespace iter_stl {
* this might or might not yield side-effects.
*/
template<class IT>
IterSnapshot (IT& src)
IterSnapshot (IT&& src)
{
for ( ; src; ++src)
buffer_.push_back(*src);
buffer_.emplace_back (*src);
}
/** build snapshot from a copy of the Lumiera Iterator
@ -443,15 +443,15 @@ namespace iter_stl {
IterSnapshot (IT const& src)
{
for (IT copy{src}; copy; ++copy)
buffer_.push_back(*copy);
buffer_.emplace_back (*copy);
}
/** take snapshot by consuming a STL iterator */
template<class IT>
IterSnapshot (IT& pos, IT const& end)
IterSnapshot (IT&& pos, IT const& end)
{
for ( ; pos!=end; ++pos)
buffer_.push_back(*pos);
buffer_.emplace_back (*pos);
}
/** take snapshot from STL iterator */
@ -459,7 +459,7 @@ namespace iter_stl {
IterSnapshot (IT const& begin, IT const& end)
{
for (IT pos{begin}; pos!=end; ++pos)
buffer_.push_back(*pos);
buffer_.emplace_back (*pos);
}
IterSnapshot(IterSnapshot &&) = default;

View file

@ -136,6 +136,13 @@ namespace lib {
}
namespace iter {
/** type binding helper: an iterato's actual result type */
template<class IT>
using Yield = decltype(std::declval<IT>().operator*());
}
/**
* Adapter for building an implementation of the »Lumiera Forward Iterator« concept.
@ -869,8 +876,11 @@ namespace lib {
* This allows to build pipelines based on all
* numbers "for `i` from `1...N`". This range is _half open_,
* i.e. the start is inclusive and the end point is exclusive.
* @remarks basically this is `boost::irange` without any boost `#include`
* @remark default constructed iters are empty and compare equal with
* any other exhausted NumIter; essential requirement for a
* Lumiera Forward Iterator (allows use in range-for-loops).
* @tparam INT a number like type, which can be incremented and compared.
* @note deliberately yields by-value and has no `operator->`
*/
template<typename INT>
class NumIter
@ -879,9 +889,9 @@ namespace lib {
INT e_;
public:
typedef const INT* pointer;
typedef const INT& reference;
typedef INT value_type;
typedef INT* pointer;
typedef INT& reference;
typedef INT value_type;
NumIter (INT start, INT end)
: i_(start)
@ -911,20 +921,13 @@ namespace lib {
/* === lumiera forward iterator concept === */
reference
value_type
operator*() const
{
_maybe_throw();
return i_;
}
pointer
operator->() const
{
_maybe_throw();
return &i_;
}
NumIter&
operator++()
{
@ -947,13 +950,18 @@ namespace lib {
/** access wrapped index elements */
const INT& getPos() const { return i_; }
const INT& getEnd() const { return e_; }
INT& getPos() const { return i_; }
INT& getEnd() const { return e_; }
ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (NumIter);
/// Supporting equality comparisons...
bool operator!= (NumIter const& o) const { return not operator==(o); }
bool operator== (NumIter const& o) const { return (empty() and o.empty()) // empty iters must be equal (Lumiera iter requirement)
or (i_ == o.i_ and e_ == o.e_); }
private:
void
_maybe_throw() const
@ -965,12 +973,6 @@ namespace lib {
/// Supporting equality comparisons...
template<class I1, class I2>
inline bool operator== (NumIter<I1> const& il, NumIter<I2> const& ir) { return (!il && !ir) || (il.getPos() == ir.getPos()); }
template<class I1, class I2>
inline bool operator!= (NumIter<I1> const& il, NumIter<I2> const& ir) { return !(il == ir); }

View file

@ -258,16 +258,9 @@ namespace lib {
{ };
/** the _value type_ yielded by a »state core« */
/** the _result type_ yielded by a »state core« */
template<class COR>
struct CoreYield
{
using Res = remove_reference_t<decltype(std::declval<COR>().yield())>;
using value_type = typename meta::RefTraits<Res>::Value;
using reference = typename meta::RefTraits<Res>::Reference;
using pointer = typename meta::RefTraits<Res>::Pointer;
};
using CoreYield = decltype(std::declval<COR>().yield());
/** decide how to adapt and embed the source sequence into the resulting IterExplorer */
@ -281,7 +274,7 @@ namespace lib {
struct _DecoratorTraits<SRC, enable_if<is_StateCore<SRC>>>
{
using SrcRaw = typename lib::meta::Strip<SRC>::Type;
using SrcVal = typename CoreYield<SrcRaw>::value_type;
using SrcVal = typename meta::RefTraits<CoreYield<SrcRaw>>::Value;
using SrcIter = lib::IterableDecorator<SrcVal, lib::CheckedCore<SrcRaw>>;
};
@ -434,7 +427,7 @@ namespace lib {
/** adapt to a functor, which accepts the value type of the source sequence ("monadic" usage pattern) */
template<class IT>
struct ArgAdapter<IT, enable_if<__and_<is_convertible<typename IT::reference, Arg>
struct ArgAdapter<IT, enable_if<__and_<is_convertible<iter::Yield<IT>, Arg>
,__not_<is_convertible<IT, Arg>>>>> // need to exclude the latter, since IterableDecorator
{ // often seems to accept IT::value_type (while in fact it doesn't)
static auto
@ -765,6 +758,11 @@ namespace lib {
* storing the treated result into an universal value holder buffer. The given functor
* is adapted in a similar way as the "expand functor", so to detect and convert the
* expected input on invocation.
* @note the result-type of the #yield() function _must be_ `reference`, even when
* the TransformFunctor produces a value; otherwise we can not provide a safe
* `operator->` on any iterator downstream. This is also the reason why the
* ItemWrapper is necessary, precisely _because we want to support_ functions
* producing a value; it provides a safe location for this value to persist.
*/
template<class SRC, class RES>
class Transformer

View file

@ -44,7 +44,7 @@ namespace lib {
auto
buildIterTuple (ITS&& ...iters)
{
return make_tuple (lib::explore (std::forward<ITS> (iters)) ...);
return std::make_tuple (lib::explore (std::forward<ITS> (iters)) ...);
}
template<class ITUP>
@ -95,14 +95,12 @@ namespace lib {
/** */
/**
* Build a tuple-combining iterator builder
* @param iters an arbitrary sequence of _iterable entities_
* @return an IterExplorer to yield result tuples on iteration
* @remark IterExplorer is both a »Lumiera Forward Itertor« and a _Pipeline Builder_
* @remark IterExplorer is both a »Lumiera Forward Iterator« and a _Pipeline Builder_
* - as Lumiera iterator, it can be used directly in _for-each_ and _while_ loops
* - result components can be picked up conveniently through _structural bindings_ for tuples
* - using the builder API, results can be postprocessed (apply a function), filtered, searched, reduced...
@ -111,7 +109,7 @@ namespace lib {
inline auto
zip (ITS&& ...iters)
{
auto access_result = [](auto& it){ return *it; };
auto access_result = [](auto& it)->decltype(auto){ return *it; }; // Note: pass-through result type (maybe reference)
auto tuple_results = [&](auto& it){ return meta::mapEach (*it, access_result); };
//
auto core = iter::ProductCore{iter::buildIterTuple (std::forward<ITS> (iters)...)};

View file

@ -280,7 +280,7 @@ namespace lib {
: IdentityCore<IT>
{
using Raw = IdentityCore<IT>;
using Val = typename IT::reference;
using Val = iter::Yield<IT>;
function<bool(Val)> predicate_;
@ -678,8 +678,8 @@ namespace lib {
template<class IT, class VAL>
class TransformingCore
{
typedef typename IT::reference InType;
typedef wrapper::ItemWrapper<VAL> Item;
using InType = iter::Yield<IT>;
using Item = wrapper::ItemWrapper<VAL>;
function<VAL(InType)> trafo_;

View file

@ -97,9 +97,8 @@ namespace util {
* @note the container is taken by \c const& and
* the \c const is \em stripped before access.
*/
template <typename COLL>
inline enable_if< treat_as_STL_Container<COLL>,
typename COLL::reference >
template <typename COLL, typename = enable_if< treat_as_STL_Container<COLL>>>
inline auto
first (COLL const& coll)
{
using lib::meta::unwrap;
@ -113,9 +112,8 @@ namespace util {
* @note the container is taken by \c const& and
* the \c const is \em stripped before access.
*/
template <typename COLL>
inline enable_if< can_direct_access_Last<COLL>,
typename COLL::reference >
template <typename COLL, typename = enable_if< can_direct_access_Last<COLL>>>
inline auto
last (COLL const& coll)
{
using lib::meta::unwrap;
@ -129,9 +127,8 @@ namespace util {
/** extract the first element yielded by an Lumiera Forward Iterator.
* @warning the iterator is modified.
*/
template <typename IT>
inline enable_if< treat_as_LumieraIterator<IT>,
typename IT::reference >
template <typename IT, typename = enable_if<treat_as_LumieraIterator<IT>>>
inline auto
first (IT ii)
{
__ensure_nonempty(ii);
@ -145,9 +142,8 @@ namespace util {
* @note returning by-value, contrary to the other tools in this suite
* @note only available when including itertools.hpp beforehand
*/
template <typename IT>
inline enable_if< treat_as_LumieraIterator<IT>,
typename IT::value_type >
template <typename IT, typename = enable_if<treat_as_LumieraIterator<IT>>>
inline auto
last (IT ii)
{
__ensure_nonempty(ii);

View file

@ -312,9 +312,9 @@ namespace test{
VERIFY_ERROR (ITER_EXHAUST, ++ii );
ii = explore (CountDown{5});
CHECK (materialise(ii) == "5-4-3-2-1");
CHECK (materialise(ii) == "5-4-3-2-1"_expect);
ii = explore (CountDown{7,4});
CHECK (materialise(ii) == "7-6-5");
CHECK (materialise(ii) == "7-6-5"_expect);
ii = explore (CountDown{});
CHECK ( isnil (ii));
CHECK (!ii);

View file

@ -19,6 +19,7 @@
#include "lib/test/run.hpp"
#include "lib/iter-zip.hpp"
#include "lib/iter-explorer.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/test/diagnostic-output.hpp"/////////////TODO
#include "lib/format-util.hpp"
@ -33,7 +34,8 @@ namespace test{
// using ::Test;
// using util::isnil;
// using LERR_(ITER_EXHAUST);
using util::join;
using LERR_(ITER_EXHAUST);
using lib::meta::forEach;
using lib::meta::mapEach;
using std::make_tuple;
@ -89,6 +91,9 @@ namespace test{
test_Fixture();
demo_mapToTuple();
demo_construction();
verify_iteration();
verify_references();
UNIMPLEMENTED ("nebbich.");
}
@ -100,17 +105,21 @@ namespace test{
auto a = std::array{1u,2u,3u};
auto v = std::vector{{2l,3l}};
for (auto [u,f] : zip(a,v))
CHECK (u + 1 == f);
// loop over both in lockstep
for (auto [u,l] : zip(a,v))
CHECK (u + 1 == l);
// iterate-with index
auto it = izip(v);
CHECK (it);
SHOW_EXPR(*it)
CHECK (*it == "«tuple<ulong, long&>»──(0,2)"_expect );
++it;
SHOW_EXPR(*it)
CHECK (*it == "«tuple<ulong, long&>»──(1,3)"_expect );
CHECK (it);
++it;
CHECK (not it);
VERIFY_ERROR (ITER_EXHAUST, *it );
VERIFY_ERROR (ITER_EXHAUST, ++it );
}
/** @test demonstrate how the test Fixture is used */
@ -272,12 +281,78 @@ SHOW_EXPR(*it)
"«tuple<int, uint>»──(1,2)-"
"«tuple<int, uint>»──(2,1)"_expect);
}
/** @test create various product (tuple) iterators
* from mixed source iterators and verify basic iteration.
*/
void
verify_iteration()
{
CHECK (materialise (
zip (num31(), num32(), num33())
)
== "«tuple<uint&, uint&, uint&>»──(1,2,3)-"
"«tuple<uint&, uint&, uint&>»──(4,5,6)-"
"«tuple<uint&, uint&, uint&>»──(7,8,9)-"
"«tuple<uint&, uint&, uint&>»──(10,11,12)-"
"«tuple<uint&, uint&, uint&>»──(13,14,15)"_expect);
CHECK (materialise(
izip (num31(), num32(), num33())
)
== "«tuple<ulong, uint&, uint&, uint&>»──(0,1,2,3)-"
"«tuple<ulong, uint&, uint&, uint&>»──(1,4,5,6)-"
"«tuple<ulong, uint&, uint&, uint&>»──(2,7,8,9)-"
"«tuple<ulong, uint&, uint&, uint&>»──(3,10,11,12)-"
"«tuple<ulong, uint&, uint&, uint&>»──(4,13,14,15)"_expect);
}
/** @test verify pass-through of references */
void
verify_references()
{
auto vec = std::vector{1,5};
auto arr = std::array{2,3};
// Case-1
auto i1 = izip (vec,arr);
CHECK (*i1 == "«tuple<ulong, int&, int&>»──(0,1,2)"_expect ); // initial state points to the first elements, prefixed with index≡0
get<1>(*i1) = 5; // manipulate through the exposed reference
CHECK (*i1 == "«tuple<ulong, int&, int&>»──(0,5,2)"_expect ); // effect of manipulation is visible
CHECK (join(vec) == "5, 5"_expect ); // manipulation indeed flipped the first element in the vector
CHECK (join(arr) == "2, 3"_expect ); // (while the array remains unaffected)
// Case-1
auto i2 = izip (explore(vec).transform([](uint v){ return v-1; }) // this time the first iterator is a pipeline with a transformer
,arr); // while the second one is again a direct iteration of the array
CHECK (*i2 == "«tuple<ulong, uint&, int&>»──(0,4,2)"_expect ); // again can see the first elements, and the effect of the transformer
get<0>(*i2) = 9; // manipulate complete result tuple
get<1>(*i2) = 9;
get<2>(*i2) = 9;
CHECK (*i2 == "«tuple<ulong, uint&, int&>»──(9,9,9)"_expect ); // effect of the manipulation is visible
++i2; // ...but iteration re-uses the internal result-tuple storage
CHECK (*i2 == "«tuple<ulong, uint&, int&>»──(1,4,3)"_expect ); // and so the effect of the manipulation seems gone
CHECK (join(vec) == "5, 5"_expect ); // ...which is in fact true for the vector, due to the transformer
CHECK (join(arr) == "9, 3"_expect ); // ...while the array could be reached through the reference
}
/*
SHOW_EXPR
(materialise (
num32().transform(hexed)
zip (num31(), num32(), num33())
)
)
CHECK (materialise (
zip (num31(), num32(), num33())
)
== ""_expect);
*/
};

View file

@ -18936,9 +18936,7 @@
</node>
<node COLOR="#33565a" CREATED="1664725557464" ID="ID_76551672" MODIFIED="1664727540443" TEXT="reduce(Icon) &#x25a3;">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Hier kein Test mehr notwendig; mehr als alles ausblenden k&#246;nnen wir nicht
@ -19177,9 +19175,7 @@
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1664543750721" ID="ID_1515243070" MODIFIED="1664836391654">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<font face="Monospaced">setName(cuString&amp;)</font>&#160;implementieren
@ -19637,9 +19633,7 @@
<node CREATED="1665874513335" ID="ID_284819629" MODIFIED="1665874526768" TEXT="Modell-A l&#xe4;&#xdf;t sich wohl als ein Spezialfall deuten">
<node CREATED="1665874544130" ID="ID_1578446031" MODIFIED="1665874578715">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
und <i><u>das</u></i>&#160;w&#228;re der <i>eigentliche Fall </i>f&#252;r einen <b>Content-Renderer</b>
@ -20160,9 +20154,7 @@
<node CREATED="1666307644363" ID="ID_1158991887" MODIFIED="1666307653429" TEXT="ja in der Tat, die Funktion ist noch sichtbar"/>
<node CREATED="1666307654257" ID="ID_662041930" MODIFIED="1666307709729" TEXT="sie schie&#xdf;t unser tolles Custom IDLabel ins Nirvana">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
und schaltet den Frame wieder zur&#252;ck auf ein Text-Label, das nat&#252;rlich dann in keinster Weise der size-Constraint-Kontrolle unterliegt
@ -21045,9 +21037,7 @@
<icon BUILTIN="up"/>
<node CREATED="1575215791195" ID="ID_398909879" MODIFIED="1575215821034" TEXT="wenig Code-Overhead">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
man mu&#223; nicht eine explizite Spezialisierung des ganzen Interfaces schreiben
@ -22626,9 +22616,7 @@
</node>
<node CREATED="1480124094867" ID="ID_1956638484" MODIFIED="1557498707225">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
<i>nach </i>der Mutation erfolgt <b>Display-Neubewertung</b>
@ -25793,9 +25781,7 @@
</node>
<node CREATED="1540511282493" ID="ID_1902168929" MODIFIED="1576282358073" TEXT="Parent-Frame hat virtuelle Methoden">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<ul>
<li>
@ -38512,9 +38498,7 @@
</node>
<node CREATED="1617898534818" ID="ID_315802107" MODIFIED="1617898613561" TEXT="und zwar gibt es demnach sogar zwei L&#xf6;sungen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
die L&#246;sung auf X-Display / GDK-Ebene f&#252;r die Maus und das grab-widget von GTK, welches alle Events fangen kann.
@ -40923,9 +40907,7 @@
<node CREATED="1667604319406" ID="ID_169844915" MODIFIED="1667604346784" TEXT="ich m&#xf6;chte den Zoom-Faktor auf eine technisch realisierbare Spanne beschr&#xe4;nken"/>
<node CREATED="1667604407474" ID="ID_1964908869" MODIFIED="1667609918926" TEXT="diese Spanne kann in der logarithmischen Skala vergleichsweise rasch durchschritten werden.">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
so &#177;15 2er-Potenz-Schritte gen&#252;gen, um von der maximalen Aufl&#246;sung in den Minuten-Bereich zu kommen
@ -42303,9 +42285,7 @@
</node>
<node COLOR="#338800" CREATED="1670287311529" ID="ID_1402443098" MODIFIED="1670370847816">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
also davor eine neue Funktion: <b>conformWindowToMetricLimits</b>(px)
@ -43199,9 +43179,7 @@
</node>
<node CREATED="1670804513145" ID="ID_877585639" MODIFIED="1670804692975" TEXT="wenn ich ohnehin mit floats rechne, dann kann ich gleich alles mit Floats rechnen">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Die Newton-Approximation kam ja nur ins Spiel, weil ich mit Integer rechnen wollte, in <i>dieser Domain</i>&#160;aber die Rechnung nicht umkehren konnte. Im weiteren Kontext betrachtet war das von Anfang an ein Schmuh (und ich habe jetzt schon zwei Tage lang ein dumpfes Gef&#252;hl, da&#223; es ein Schmuh ist....)
@ -43803,9 +43781,7 @@
<arrowlink COLOR="#ffe1c1" DESTINATION="ID_394250867" ENDARROW="Default" ENDINCLINATION="-128;27;" ID="Arrow_ID_791821354" STARTARROW="None" STARTINCLINATION="-142;-24;"/>
<node CREATED="1668395067578" ID="ID_386803191" MODIFIED="1668395176399" TEXT="das liegt aber nur am fehlenden -1 Branch">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
Die Vorlage auf Stackoverflow initialisiert auf 0 oder -1, l&#228;uft dann aber f&#252;r Input==0 leer durch die Checks durch. Meine Variante testet auf 0 und returnt sofort.
@ -44180,9 +44156,7 @@
<icon BUILTIN="help"/>
<node CREATED="1669932795247" ID="ID_258240741" MODIFIED="1669932979085" TEXT="Zeit in Lumiera stets left-Truncate">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<head/>
<body>
<p>
das ist essentiell wichtig. &quot;Negative&quot; Zeiten d&#252;rfen sich <i>keinesfalls</i>&#160; anders verhalten. Eine andere Quantsierungs-Regel kann man dann ggfs. high-level auf ein left-Truncate aufsetzen (z.B. Mitte Frame-Intervall)
@ -45625,9 +45599,7 @@
</node>
<node CREATED="1541790399905" ID="ID_552609912" MODIFIED="1541790483789">
<richcontent TYPE="NODE"><html>
<head>
</head>
<head/>
<body>
<p>
aber: zuf&#228;llige ID macht Objekt-builder <i>stateful</i>
@ -52948,7 +52920,7 @@
</node>
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1732235208972" ID="ID_1764687143" MODIFIED="1732308740170" TEXT="nun in Library-Code extrahieren">
<icon BUILTIN="pencil"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1732299521810" ID="ID_185815307" MODIFIED="1732299541201" TEXT="schlank halten: es gen&#xfc;gt die ProductCore">
<node COLOR="#435e98" CREATED="1732299521810" ID="ID_185815307" MODIFIED="1732313502381" TEXT="schlank halten: es gen&#xfc;gt die ProductCore">
<icon BUILTIN="yes"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1732299561444" ID="ID_1140916206" MODIFIED="1732299624657" TEXT="dazu eine free-function iter::buildIterTuple(its...)">
@ -52957,6 +52929,183 @@
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1732308743486" ID="ID_1261102696" MODIFIED="1732308787453" TEXT="Pr&#xfc;fen und erweitern auf das Durchreichen von Referenzen">
<linktarget COLOR="#b36e78" DESTINATION="ID_1261102696" ENDARROW="Default" ENDINCLINATION="243;11;" ID="Arrow_ID_1182778536" SOURCE="ID_1663970369" STARTARROW="None" STARTINCLINATION="212;14;"/>
<icon BUILTIN="flag-pink"/>
<node BACKGROUND_COLOR="#f8f1cb" COLOR="#a50125" CREATED="1732315275749" ID="ID_769235796" MODIFIED="1732315292779" TEXT="liefert dann &#xfc;berraschend oft eine Referenz">
<icon BUILTIN="messagebox_warning"/>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1732315295690" ID="ID_565969002" MODIFIED="1732315304625" TEXT="m&#xf6;chte man das?"/>
<node CREATED="1732315305473" ID="ID_1790636201" MODIFIED="1732315324906" TEXT="ja &#x2014; und es gibt const">
<node CREATED="1732315656617" ID="ID_1754114367" MODIFIED="1732315684037" TEXT="bei Containern und Services kann man davon ausgehen da&#xdf; die Problematik bekannt ist"/>
<node CREATED="1732315685980" ID="ID_543097466" MODIFIED="1732315711158" TEXT="und dem User kann ein gewisser Grad an Intelligenz unterstellt werden"/>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1732315327534" ID="ID_1282656380" MODIFIED="1732315716097" TEXT="&#xfc;berraschend beim Loop-Index">
<icon BUILTIN="broken-line"/>
<node CREATED="1732315341532" ID="ID_42867523" MODIFIED="1732315347625" TEXT="NumIter liefert eine const&amp;"/>
<node CREATED="1732315348475" ID="ID_681059696" MODIFIED="1732315437859" TEXT="das ist jetzt die erste echte Verwednung">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
NumIter hatte ich bei Gelegenheit aus Test-Code extrahiert, ohne weiter viel Gedanken darauf zu ver(sch)wenden....
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1732315439551" ID="ID_933184220" MODIFIED="1732315647938" TEXT="eine Referenz auf eine einfache Zahl ist selten sinnvoll">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Bestenfalls eliminiert der Optimiser ohnehin alle Indirektionen, aber auch alle Kopien. Wenn das aber nicht geht, weil es von irgendwo noch einen Zugriff geben k&#246;nnte, dann sitzt man auf einem Speicherzugriff, wo andernfalls direkt ein Register verwendet werden k&#246;nnte. Und wenn dann auch noch die Referenz non-const ist, versaut man sich leicht internen State und wundert sich dann... Nee, nee! Wenn man wirklich Seiteneffekte &#252;ber Referenzen m&#246;chte, dann soll man sich das bitte explizit auscoden, aber nicht eine Library-Funktion kreativ nutzen
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1732315722881" ID="ID_506428359" MODIFIED="1732315730323" TEXT="also hier stellen wir um">
<node CREATED="1732315731512" ID="ID_70704811" MODIFIED="1732315759207" TEXT="die yield-Operation liefert explizit die Zahl by-value"/>
<node CREATED="1732315759868" ID="ID_1323105276" MODIFIED="1732315833747" TEXT="der operator-&gt; wird sogar entfernt">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
ich kann mir keinen Anwendungsfall vorstellen, wo so etwas nicht zumindest <i>&#252;berraschend</i>&#160;w&#228;re.... Ja man k&#246;nnte INT = custom magic type setzen, aber wie war das nochmal mit <i>Magie und so?</i>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1732317048384" ID="ID_146419454" MODIFIED="1732317054284" TEXT="Konsequenzen">
<node BACKGROUND_COLOR="#fafe99" COLOR="#fa002a" CREATED="1732317059614" ID="ID_20106465" MODIFIED="1732317075988" TEXT="Problem mit stringify / Itertools - TransformIter">
<icon BUILTIN="broken-line"/>
<node CREATED="1732317140456" ID="ID_837986381" MODIFIED="1732317155688" TEXT="kann nicht double&amp; an double-val binden">
<icon BUILTIN="stop-sign"/>
</node>
<node COLOR="#435e98" CREATED="1732317156849" ID="ID_255372861" MODIFIED="1732322150442" TEXT="wie kommt das zustande?">
<node CREATED="1732317164400" ID="ID_1970930063" MODIFIED="1732317249441" TEXT="in TransformIter ist ein &#xbb;signature-check&#xab; eingebaut">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Das hei&#223;t: in dem Moment wo wir die transformer-Funktion tats&#228;chlich installieren, packen wir sie in ein std::function-Objekt mit einer <b>neu synthetisierten Signatur</b>. Diese ist (der Intention nach) pa&#223;genau, d.h. sie nimmt den yield des vorgelagerten Iterators als Input
</p>
</body>
</html>
</richcontent>
</node>
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1732317252324" ID="ID_417114818" MODIFIED="1732322136155" TEXT="hier liegt der Hund begraben...">
<icon BUILTIN="broken-line"/>
<node CREATED="1732317307077" ID="ID_577545728" MODIFIED="1732322142648" STYLE="bubble">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
<font face="Monospaced">typedef typename IT::</font><font face="Monospaced" color="#c81212">reference</font><font face="Monospaced">&#160;InType; </font>
</p>
<p>
<font face="Monospaced">function&lt;VAL(InType)&gt; trafo_; </font>
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1732317376563" ID="ID_627865570" MODIFIED="1732317617944" TEXT="das ist ein Schnellschlu&#xdf;...">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
damals wollte ich erst mal schnell durch, wie &#252;blich;
</p>
<p>
viele Jahre sp&#228;ter habe ich dann den NumIter definiert, und das ist vielleicht das erste Beispiel, bei dem dieses neue Konzept wirklich ausgereitzt wurde. Ich habe so dunkel in Erinnerung, da&#223; es dann nicht funktioniert hat, und ich deshalb &#8222;einfach&#8220; das <font color="#7510cd" face="Monospaced">const</font>&#160;in die eingebetteten Ergebnis-Typdefinitionen gepackt habe. Was ja nicht falsch war, aber der Weg des geringsten Wiederstandes
</p>
</body>
</html>
</richcontent>
</node>
<node CREATED="1732317416174" ID="ID_1286735666" MODIFIED="1732317436999" TEXT="es ist in 90% der F&#xe4;lle in der Praxis so"/>
<node CREATED="1732317386082" ID="ID_1276663187" MODIFIED="1732317855187" TEXT="Nach aktuellem Stand gibt es aber keine entsprechende Konvention">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
Und das ist mir zunehmend wichtiger geworden, vor allem nach meinen Erfahrungen mit dem monadischen IterExplorer v1. Grade <i>weil man manchmal wirklich nur Values bieten kann,</i>&#160;mu&#223; diese Hintert&#252;r offen bleiben. Andererseits w&#228;re es ein gef&#228;hrlicher Fehlschlu&#223;, da&#223; eine Type-def &#187;reference&#171; hier &#8222;in Wirkklichkeit&#8220; meint, das was der Iterator liefert. Der Schlu&#223; liegt nahe, und deshalb bin ich ihm hier auch verfallen. Aber wenn man mit derartigem Konzept-Mapping erst mal anf&#228;ngt, dann verliert man schnell die Kontrolle
</p>
</body>
</html>
</richcontent>
</node>
</node>
<node COLOR="#338800" CREATED="1732317867385" ID="ID_1371439047" MODIFIED="1732322117846" TEXT="also: stattdessen explizit den realen yield-Typ verwenden">
<icon BUILTIN="button_ok"/>
<node COLOR="#338800" CREATED="1732318665574" ID="ID_1457902866" MODIFIED="1732322128177" TEXT="daf&#xfc;r eine neue Typfunktion: iter::Yield&lt;IT&gt;">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
in iter-adapter.hpp
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="button_ok"/>
</node>
<node COLOR="#338800" CREATED="1732318689596" ID="ID_1684194462" MODIFIED="1732322119411" TEXT="nach weiteren &#xe4;hnlichen Kurzschl&#xfc;ssen suchen...">
<icon BUILTIN="button_ok"/>
<node COLOR="#435e98" CREATED="1732319377134" ID="ID_1458322060" MODIFIED="1732322123341" TEXT="weiterer Fall in Itertools (im Filter)"/>
<node COLOR="#435e98" CREATED="1732318704077" ID="ID_1614481458" MODIFIED="1732322123344" TEXT="HA! iter-explorer : ArgAdapter-Magic">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
also exakt die zentrale Stelle, an der entschieden wird, ob eine nachgeschaltete Funktion auf den Resultat-Wert losgeht, oder direkt auf den Iterator-Typ zugreift
</p>
</body>
</html>
</richcontent>
</node>
<node COLOR="#435e98" CREATED="1732319784560" ID="ID_866009173" MODIFIED="1732322123344" TEXT="&#xe4;hnliches Denkmuster auch in util-coll">
<node COLOR="#435e98" CREATED="1732319797920" ID="ID_1305250293" MODIFIED="1732319806708" TEXT="hier ist auto viel besser!">
<icon BUILTIN="yes"/>
</node>
</node>
</node>
</node>
</node>
<node COLOR="#5b280f" CREATED="1732322088730" ID="ID_1242739907" MODIFIED="1732323499529" TEXT="w&#xe4;re das auch anwendbar auf IterExplorer.transform() und expand() ?">
<icon BUILTIN="help"/>
<icon BUILTIN="closed"/>
<node CREATED="1732322588222" ID="ID_1443186617" MODIFIED="1732322613161">
<richcontent TYPE="NODE"><html>
<head/>
<body>
<p>
jetzt wirds aber <b><font color="#e82105">brandgef&#228;hrlich</font></b>
</p>
</body>
</html></richcontent>
</node>
<node CREATED="1732322629737" ID="ID_676096219" MODIFIED="1732322648571" TEXT="operator-&gt; k&#xf6;nnte Adresse-von-Temporary nehmen">
<icon BUILTIN="broken-line"/>
</node>
<node CREATED="1732323357278" ID="ID_1689757044" MODIFIED="1732323387677" TEXT="unm&#xf6;glich da wir effektiv nur einen Ausgabepfad haben">
<node CREATED="1732323518400" ID="ID_1448081421" MODIFIED="1732323556103" TEXT="operator-&gt; verlangt zwingend nach einem stabilen Value"/>
<node CREATED="1732323556923" ID="ID_1568353234" MODIFIED="1732323592138" TEXT="daher kann Core::yield() niemals anders als per Ref auf einen stabilen Wert arbeiten"/>
<node CREATED="1732323615259" ID="ID_183489075" MODIFIED="1732323721859" TEXT="wollte man hier flexibel sein, ginge das stets nur an der Au&#xdf;engrenze">
<richcontent TYPE="NOTE"><html>
<head/>
<body>
<p>
...das w&#252;rde bedeuten: man reicht eine weitere Typ-Def komplett durch die ganze Kette durch, und jeweils nur am Ende der Kette w&#252;rde diese f&#252;r den operator* gelten. Da wir aber Ketten im Builder auch noch nachtr&#228;glich weiter verl&#228;ngern, indem eine neue Core dar&#252;ber gesetzt wird, ist das jedoch nicht ohne Weiteres realisierbar
</p>
</body>
</html>
</richcontent>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1732235272468" ID="ID_1892180908" MODIFIED="1732235318053" TEXT="gr&#xfc;ndlich testen">
@ -52968,6 +53117,14 @@
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1732235323997" ID="ID_1085200650" MODIFIED="1732235555231" TEXT="Iteratoren verschiedenen Typs">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1732313512667" ID="ID_1362209953" MODIFIED="1732313522016" TEXT="verschieden dekorierte Sequenzen"/>
<node CREATED="1732313524489" ID="ID_824059713" MODIFIED="1732313531717" TEXT="Sequenzen verschiedener L&#xe4;nge"/>
<node CREATED="1732313533659" ID="ID_1229132868" MODIFIED="1732313539891" TEXT="verschiedene Quellen">
<node CREATED="1732313542680" ID="ID_918133774" MODIFIED="1732313546301" TEXT="Lumiera-Iterator"/>
<node CREATED="1732313547158" ID="ID_1297222060" MODIFIED="1732313551929" TEXT="STL-Container"/>
<node CREATED="1732313554272" ID="ID_628954162" MODIFIED="1732313557682" TEXT="State-Core"/>
<node CREATED="1732313559148" ID="ID_888513620" MODIFIED="1732313564479" TEXT="IterSource"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1732235343138" ID="ID_1943784376" MODIFIED="1732235555231" TEXT="per structured Binding verarbeiten">
<icon BUILTIN="flag-yellow"/>