diff --git a/src/lib/diff/record.hpp b/src/lib/diff/record.hpp index d3a366dd6..9860e4a0a 100644 --- a/src/lib/diff/record.hpp +++ b/src/lib/diff/record.hpp @@ -426,7 +426,8 @@ namespace diff{ void swap (Rec& existingInstance) noexcept { - std::swap (existingInstance, record_); + using std::swap; + swap (existingInstance, record_); } bool @@ -641,7 +642,7 @@ namespace diff{ RecordRef& operator= (RecordRef &&o) { - std::swap(record_, o.record_); + std::swap (record_, o.record_); return *this; } diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index 54670e223..70386552c 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -551,6 +551,8 @@ namespace lib { CheckedCore& operator= (CheckedCore&&) =default; CheckedCore& operator= (CheckedCore const&) =default; + using TAG_CheckedCore_Raw = COR; ///< marker to allow unwrapping the raw core + /* === state protocol API for IterStateWrapper === */ bool diff --git a/src/lib/iter-explorer.hpp b/src/lib/iter-explorer.hpp index cf3712a16..0e4429e90 100644 --- a/src/lib/iter-explorer.hpp +++ b/src/lib/iter-explorer.hpp @@ -264,7 +264,9 @@ namespace lib { using CoreYield = decltype(std::declval().yield()); - /** decide how to adapt and embed the source sequence into the resulting IterExplorer */ + /** + * @internal Type-selector template to adapt for IterExplorer: + * decide how to adapt and embed the source sequence */ template struct _DecoratorTraits { @@ -513,6 +515,8 @@ namespace lib { void expandChildren() { } ///< collaboration: recurse into nested scope size_t depth() const { return 0; } ///< collaboration: number of nested scopes + + using TAG_IterExplorer_BaseAdapter = SRC; ///< @internal for \ref _BaseDetector }; @@ -1578,6 +1582,8 @@ namespace lib { using reference = typename meta::ValueTypeBinding::reference; using pointer = typename meta::ValueTypeBinding::pointer; + using TAG_IterExplorer_Src = SRC; ///< @internal for \ref _PipelineDetector + /** pass-through ctor */ using SRC::SRC; @@ -2056,6 +2062,61 @@ namespace lib { }; + namespace {// internal logic to pick suitable pipeline adapters... + + /** Detect or otherwise add BaseAdapter. + * @remark in addition to just iteration, IterExplorer uses an internal wiring for some + * of the additional processing layers, which works by calling to the base class. + * When building a new pipeline, a BaseAdapter is added on top of the raw iterator + * to absorb these internal calls (and do nothing); however, if the raw iterator + * in fact is already a pipeline built by IterExplorer, than no BaseAdapter is + * required and rather both pipelines can be connected together + */ + template + struct _BaseDetector + { + using BaseAdapter = iter_explorer::BaseAdapter; + }; + + template // used when type tag is present on some baseclass + struct _BaseDetector > + { + using BaseAdapter = SRC; + }; + + + /** Detect and remove typical adapter layers added by a preceding IterExplorer usage */ + template + struct _UnstripAdapter + { + using RawIter = SRC; + }; + + template // used when actually a CheckedCore was attached + struct _UnstripAdapter > + { + using RawIter = typename COR::TAG_CheckedCore_Raw; + }; + + + /** Detect if given source was already built by IterExplorer; + * @remark when building on-top of an existing pipeline, some adapter can be stripped + * to simplify the type hierarchy; for this purpose, IterExplorer places a tag type + * into its own products, which point to a suitable source type below the adapter. + */ + template + struct _PipelineDetector + { + using RawIter = SRC; + }; + template + struct _PipelineDetector > + { + using _SrcIT = typename SRC::TAG_IterExplorer_Src; + using RawIter = typename _UnstripAdapter<_SrcIT>::RawIter; + }; + }//(End)internal adapter logic + @@ -2116,8 +2177,9 @@ namespace lib { inline auto explore (IT&& srcSeq) { - using SrcIter = typename _DecoratorTraits::SrcIter; - using Base = iter_explorer::BaseAdapter; + using RawIter = typename _PipelineDetector::RawIter; // possibly strip an underlying IterExplorer + using SrcIter = typename _DecoratorTraits::SrcIter; // then decide how to adapt the source / iterator + using Base = typename _BaseDetector::BaseAdapter; // detect if a BaseAdapter exists or must be added return IterExplorer (std::forward (srcSeq)); } diff --git a/src/lib/iter-zip.hpp b/src/lib/iter-zip.hpp index 25e2786ce..f52732836 100644 --- a/src/lib/iter-zip.hpp +++ b/src/lib/iter-zip.hpp @@ -84,6 +84,32 @@ namespace lib { meta::forEach (iters_ ,[](auto& it){ ++it; }); } + + + /* === connector for IterAdapter internal protocol === */ + + /** + * instruct a follow-up IterAdapter not to add a BaseAdapter + * but rather to connect to the dispatcher functions defined here + */ + using TAG_IterExplorer_BaseAdapter = ITUP; + + /** delegate to the IterExplorers in the tuple */ + void + expandChildren() + { + meta::forEach (iters_ + ,[](auto& it){ it.expandChildren(); }); + } + + size_t + depth() const + { + size_t maxDepth{0}; + meta::forEach (iters_ + ,[&](auto& it){ maxDepth = std::max (maxDepth, it.depth()); }); + return maxDepth; + } }; } // namespace lib::iter diff --git a/src/lib/path-array.hpp b/src/lib/path-array.hpp index 626896e2a..120d67012 100644 --- a/src/lib/path-array.hpp +++ b/src/lib/path-array.hpp @@ -130,26 +130,9 @@ namespace lib { std::swap (storage_, rr.storage_); } - Extension& operator= (Extension const& o) + Extension& operator= (Extension o) { - if (this != &o) - { - std::unique_ptr cp; - if (o.storage_) - cp.reset (o.newCopy()); - if (storage_) - delete[] storage_; - storage_ = cp.release(); - } - return *this; - } - - Extension& operator= (Extension&& rr) noexcept - { - if (this != &rr) - { - std::swap (storage_, rr.storage_); - } + std::swap (storage_, o.storage_); return *this; } diff --git a/src/lib/random-draw.hpp b/src/lib/random-draw.hpp index 49ed8f310..4de2cc419 100644 --- a/src/lib/random-draw.hpp +++ b/src/lib/random-draw.hpp @@ -380,7 +380,7 @@ namespace lib { /** @internal adapt output side of a given function, allowing to handle it's results * - a function producing the overall result-type is installed as-is - * - a `size_t` result is assumed be a hash and passed into #drawLimited + * - a `size_t` result is assumed to be a hash and passed into #drawLimited * - likewise a `double` is assumed to be already a random val to be #limited * - special treatment is given to a function returning a `RandomDraw` instance * by value; such a function is assumed to set some parametrisation based diff --git a/src/lib/stat/data.hpp b/src/lib/stat/data.hpp index 9a0d2e68d..b40cf4e01 100644 --- a/src/lib/stat/data.hpp +++ b/src/lib/stat/data.hpp @@ -231,7 +231,8 @@ namespace stat{ CSVData csv{{}}; csv.reserve (size()+1); auto header = generateHeaderSpec(); - std::swap (csv[0], header); + using std::swap; + swap (csv[0], header); for (uint i=0; i < size(); ++i) csv.emplace_back (formatCSVRow(i)); return csv; diff --git a/src/lib/text-template.hpp b/src/lib/text-template.hpp index d1d1c5190..6fa19255b 100644 --- a/src/lib/text-template.hpp +++ b/src/lib/text-template.hpp @@ -912,7 +912,8 @@ namespace lib { } else { // restore original data context - std::swap (dataSrc_, ctxStack_.top().second); + using std::swap; + swap (dataSrc_, ctxStack_.top().second); ctxStack_.pop(); return false; } diff --git a/src/lib/uninitialised-storage.hpp b/src/lib/uninitialised-storage.hpp index b6f10e62e..8402c6782 100644 --- a/src/lib/uninitialised-storage.hpp +++ b/src/lib/uninitialised-storage.hpp @@ -179,8 +179,9 @@ namespace lib { friend void swap (UninitialisedDynBlock& u1, UninitialisedDynBlock& u2) { - std::swap (u1.size_, u2.size_); - std::swap (u1.buff_, u2.buff_); + using std::swap; + swap (u1.size_, u2.size_); + swap (u1.buff_, u2.buff_); } explicit diff --git a/tests/library/iter-zip-test.cpp b/tests/library/iter-zip-test.cpp index 8c2b1cc60..9ecaf78ed 100644 --- a/tests/library/iter-zip-test.cpp +++ b/tests/library/iter-zip-test.cpp @@ -66,7 +66,48 @@ namespace test{ #define TYPE(_EXPR_) showType() + template + struct _PipelineDetector + { + using RawIter = SRC; + }; + template + struct _PipelineDetector > + { + using RawIter = typename SRC::TAG_Explode; + }; + struct BOO + { + int uh{42}; + }; + + template + struct Moo + : SRC + { + using TAG_Explode = SRC; + }; + + template + struct D + : SRC + { }; + + void + plonk() + { + using P1 = D>; + using P2 = D>>>; + + using R1 = typename _PipelineDetector::RawIter; + using R2 = typename _PipelineDetector::RawIter; + +SHOW_TYPE(P1) +SHOW_TYPE(R1) +SHOW_TYPE(P2) +SHOW_TYPE(R2) + } /*********************************************************************************//** @@ -85,6 +126,7 @@ namespace test{ virtual void run (Arg) { + plonk(); simpleUsage(); test_Fixture(); demo_mapToTuple(); @@ -409,27 +451,41 @@ namespace test{ /** @test the result is actually an IterExplorer pipeline builder, - * which can be used to attach further processing + * which can be used to attach further processing. + * @note the design of IterExplorer inherently requires that + * generic lambdas accept the _iterator type_ by reference; + * structural bindings can only be used in a second step. */ void verify_pipelining() { -SHOW_EXPR - (materialise ( + // transform the tuple into another data value + CHECK (materialise ( zip (num31(), num32(), num33()) . transform([](auto& it){ auto [a,b,c] = *it; return a+b+c; }) ) - ) -SHOW_EXPR - (materialise ( + == "6-15-24-33-42"_expect); + + // filter tuples based on inspecting contents + CHECK (materialise ( zip (num31(), num32(), num33()) . filter ([](auto& it){ auto [a,b,c] = *it; return not ((a+b+c) % 2); }) ) - ) + == "«tuple»──(1,2,3)-" + "«tuple»──(7,8,9)-" + "«tuple»──(13,14,15)"_expect); + + // reduce with accessor and std::plus + CHECK (zip (num31(), num32(), num33()) + . reduce ([](auto& it){ auto [a,b,c] = *it; + return a+b+c; + }) + == 6+15+24+33+42); +SHOW_EXPR(TYPE(izip(num31()))) } /* SHOW_EXPR diff --git a/tests/stage/model/w-link-test.cpp b/tests/stage/model/w-link-test.cpp index ca1118b9b..0cbf23717 100644 --- a/tests/stage/model/w-link-test.cpp +++ b/tests/stage/model/w-link-test.cpp @@ -169,7 +169,7 @@ namespace test { CHECK (w1->val == l1->val); CHECK (w1->val == l3->val); - std::swap (l2, l3); + swap (l2, l3); CHECK (w1->val == l1->val); CHECK (w1->val == l2->val); CHECK (w2->val == l3->val); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 680b285af..71519ef76 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -19375,9 +19375,7 @@ - - - +

...die name-ID muß eindeutig sein (modulo Objekt-Typ), weil allein daraus eine EntryID zu konstruieren ist, vermöge deren die Kommunikation über den Bus gesteuert wird. Daher ist es denkbar, daß die User [optional] eine mnemonische Form definieren wollen, und diese steht dann im Label-Widget. Und noch etwas: der Label-Text wird ggfs. zur Anzeige gekürzt, also muß irgendwo der Basis-Text stehen (es sei denn, man holt sich den via Request über den Bus) @@ -19754,9 +19752,7 @@ - - - +

...wannimmersich die Display-Metrik ändert (bei jeder Zoom-Anpassung!) @@ -20185,9 +20181,7 @@ - - - +

get_has_window()  ➔ false @@ -20737,9 +20731,7 @@ - - - +

Erläuterung: man könnte auf die Idee kommen, die vier notwendigen Operationen auf dem Ziel durch Lambdas zu verkapseln. Wenn man dann aber nicht aufpaßt, resultiert das in einer Closure für jedes dieser vier Lamdas, und diese Closure hält zumindest einen Pointer auf das Zielobjekt. Der Vorteil eines solchen Ansatzes wäre natürlich, daß der konkrete Typ von Quelle und Ziel aus der Definition des ViewHook verschwindet (allerdings auch nur, wenn diese Lambdas in std::function-Objekte gewickelt sind) @@ -21624,9 +21616,7 @@ - - - +

dieser greift im »Constructor« binding... @@ -23337,9 +23327,7 @@ - - - +

per »einhäkel-λ« @@ -26667,9 +26655,7 @@ - - - +

wenn das so relevant werden sollte @@ -36842,9 +36828,7 @@ - - - +

wohl einzige verbleibende Verwendung @@ -40024,9 +40008,7 @@ - - - +

bedingt durch die interne Repräsesntation (als 64bit µ-Ticks bzw. signed fraction)... @@ -41555,9 +41537,7 @@ - - - +

Mathematik halt.... @@ -42435,9 +42415,7 @@ - - - +

anders im Nenner;  md * dd ist garantiert berechenbar, sofern die Duration selber aus einem time::Duration gebildet wurde (und md ist durch das detox() limitiert worden) @@ -43053,9 +43031,7 @@ - - - +

die MAX_TIMESPAN-Limitierung beginnt etwas über 1000px zu greifen; diese Unterschwelle wäre aber px · 1e-14 @@ -43491,9 +43467,7 @@ - - - +

selbst Sound-Samples sind (absolut betrachet) noch 10.41ms auseinander; solange wir das komfortabel und sauber im GUI darstellen und handhaben können, sind wir fein @@ -43767,9 +43741,7 @@ - - - +

eine andere Standard-Library, und ilogb() könnte deutlich langsamer sein. @@ -52784,8 +52756,9 @@ - - + + + @@ -52860,6 +52833,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ andere Tricks mit der _rawCore()-Zugriffsfunktion scheinen nicht zu gehen +

+ + +
+
+ + + + +

+ ...da alle Processing-Layer auf State-Cores beruhen, präsentieren wir dem darüberzulegenden IterExplorer die neue Core, und der findet dann die unter diesem Layer liegende CheckedCore des Vorgängers und strippt den neuen Layer weg. YESS es funktioniert!!!!!! +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

+ vorher: +

+

+ IterExplorer< +

+

+   BaseAdapter< +

+

+     IterableDecorator<uint, +

+

+       CheckedCore< +

+

+         IterExplorer< +

+

+           IterableDecorator<uint, +

+

+             CheckedCore< +

+

+               Transformer< +

+

+                 BaseAdapter<NumIter<int> >, +

+

+                 uint +

+

+ nachher: +

+

+ IterExplorer< +

+

+   IterableDecorator<uint, +

+

+     CheckedCore< +

+

+       Transformer< +

+

+         BaseAdapter<NumIter<int> >, +

+

+         uint +

+ +
+ +
+
+ + @@ -53088,16 +53198,20 @@ - - + + + + + + - + @@ -53125,10 +53239,31 @@ - - - + + + + + + + + + +

+ tatsächlich ist der Filter besonders gefährdet +

+ +
+ + + +

+ weil der Filter selber ja nur den Feed pullt, aber selber keine Werte speichert; damit erzeugt er möglicherweise upstream obsolete Referenzen. +

+ + +
+
@@ -53166,12 +53301,36 @@
+ + + + +

+ ungutes Gefühl... +

+

+ das Design hat hier eine Schwachstelle +

+ + +
+ + +
+
+ +
+ + + + +
@@ -54443,6 +54602,28 @@
+ + + + + + + +

+ Diese Gefahr resultiert exakt aus seiner Stärke, daß er nämlich jede beliebige Funktion adaptieren kann, also auch eine Funktion, die Referenzen liefert. Wenn diese Referenzen in internen State der Iterator-Pipeline zeigen, dann werden sie dangling, sobald man die Pipeline verschiebt. Und das passiert leider bereits bei der Konstruktion. Wenn dann hinter dem Transformer noch ein Filter hängt, nimmt das Verhängnis seinen Lauf +

+ +
+ + + + + + + + + +