From 99c4663719768d56e675662b2b4f948dbb087014 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 26 Nov 2024 22:15:33 +0100 Subject: [PATCH] Library: simplify state-core wrapper parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As follow-up from the preceding refactorings, it is now possible to drastically simplify several type signatures. Generally speaking, iterator pipelines can now pass-through the result type, and thus it is no longer necessary to handle this result type explicitly In the case of `IterStateWrapper`, the result type parameter was retained, but moved to the second position and defaulted; sometimes it can be relevant to force a specific type; this is especially useful when defining an `iterator` and a `const_iterator` based on the same »state-core« --- src/lib/diff/gen-node.hpp | 4 +- src/lib/diff/list-diff-detector.hpp | 2 +- src/lib/index-iter.hpp | 4 +- src/lib/iter-adapter.hpp | 62 ++++----- src/lib/iter-cursor.hpp | 4 +- src/lib/iter-explorer.hpp | 2 +- src/lib/iter-stack.hpp | 4 +- src/lib/linked-elements.hpp | 4 +- src/vault/gear/block-flow.hpp | 2 +- src/vault/mem/extent-family.hpp | 2 +- tests/library/iter-core-adapter-test.cpp | 8 +- tests/library/iter-explorer-test.cpp | 6 +- tests/library/iter-zip-test.cpp | 12 +- tests/library/text-template-test.cpp | 2 +- wiki/thinkPad.ichthyo.mm | 155 +++++++++++++++-------- 15 files changed, 154 insertions(+), 119 deletions(-) diff --git a/src/lib/diff/gen-node.hpp b/src/lib/diff/gen-node.hpp index 4839480d8..fe22ebb20 100644 --- a/src/lib/diff/gen-node.hpp +++ b/src/lib/diff/gen-node.hpp @@ -594,7 +594,7 @@ namespace diff{ */ class GenNode::ScopeExplorer { - using ScopeIter = IterStateWrapper; + using ScopeIter = IterStateWrapper; std::deque scopes_; @@ -660,7 +660,7 @@ namespace diff{ struct GenNode::ScopeExplorerIterator - : IterStateWrapper + : IterStateWrapper { using IterStateWrapper::IterStateWrapper; diff --git a/src/lib/diff/list-diff-detector.hpp b/src/lib/diff/list-diff-detector.hpp index a53e5099c..3c2b12d1a 100644 --- a/src/lib/diff/list-diff-detector.hpp +++ b/src/lib/diff/list-diff-detector.hpp @@ -118,7 +118,7 @@ namespace diff{ /** Diff is a iterator to yield a sequence of DiffStep elements */ - using Diff = lib::IterStateWrapper; + using Diff = lib::IterStateWrapper; /** Diff generation core operation. * Take a snapshot of the \em current state of the underlying sequence diff --git a/src/lib/index-iter.hpp b/src/lib/index-iter.hpp index be5975c44..532560cac 100644 --- a/src/lib/index-iter.hpp +++ b/src/lib/index-iter.hpp @@ -53,8 +53,6 @@ namespace lib { using value_type = typename meta::RefTraits::Value; using reference = typename meta::RefTraits::Reference; - using IterWrapper = lib::IterStateWrapper; - bool checkPoint() const { @@ -81,6 +79,8 @@ namespace lib { and idx < data_->size(); } + using IterWrapper = lib::IterStateWrapper; + friend bool operator== (IndexAccessCore const& c1, IndexAccessCore const& c2) { diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index fadacc1e4..7cdf425b0 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -360,25 +360,24 @@ namespace lib { * -# \c checkPoint establishes if the given state element represents a valid active state * -# \c iterNext evolves this state by one step (sideeffect) * -# \c yield realises the given state, yielding an element of _result type_ \a T - * @tparam T nominal result type (maybe const, but without reference). - * The resulting iterator will yield a reference to this type T * @tparam ST type of the »state core«, defaults to T. * The resulting iterator will hold an instance of ST, which thus * needs to be copyable and default constructible to the extent * this is required for the iterator as such. + * @tparam T (optional) result type, usually deduced from ST::yield * @see IterableDecorator for variation of the same concept * @see iter-explorer-test.hpp * @see iter-adaptor-test.cpp */ - template + template> class IterStateWrapper { ST core_; public: - typedef T* pointer; - typedef T& reference; - typedef T value_type; + using value_type = typename meta::RefTraits::Value; + using reference = typename meta::RefTraits::Reference; + using pointer = typename meta::RefTraits::Pointer; IterStateWrapper (ST&& initialState) : core_(std::forward(initialState)) @@ -401,7 +400,7 @@ namespace lib { /* === lumiera forward iterator concept === */ - reference + T operator*() const { __throw_if_empty(); @@ -411,8 +410,15 @@ namespace lib { pointer operator->() const { - __throw_if_empty(); - return & core_.yield(); // core interface: yield + if constexpr (meta::isLRef_v) + { + __throw_if_empty(); + return & core_.yield(); // core interface: yield + } + else + static_assert (!sizeof(T), + "can not provide operator-> " + "since iterator pipeline generates a value"); } IterStateWrapper& @@ -455,24 +461,24 @@ namespace lib { ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (IterStateWrapper); /// comparison is allowed to access state implementation core - template - friend bool operator== (IterStateWrapper const&, IterStateWrapper const&); + template + friend bool operator== (IterStateWrapper const&, IterStateWrapper const&); }; /// Supporting equality comparisons of equivalent iterators (same state type)... - template + template inline bool - operator== (IterStateWrapper const& il, IterStateWrapper const& ir) + operator== (IterStateWrapper const& il, IterStateWrapper const& ir) { return (il.empty() and ir.empty()) or (il.isValid() and ir.isValid() and il.core_ == ir.core_); } - template + template inline bool - operator!= (IterStateWrapper const& il, IterStateWrapper const& ir) + operator!= (IterStateWrapper const& il, IterStateWrapper const& ir) { return not (il == ir); } @@ -656,13 +662,12 @@ namespace lib { * it is guaranteed to be valid (by contextual knowledge). It might be a good idea * to build some safety checks into the Core API functions instead, maybe even just * as assertions, or to wrap the Core into \ref CheckedCore for most usages. - * @tparam T nominal result type (maybe const, but without reference). * @tparam COR type of the »state core«. The resulting iterator will _mix-in_ this type, * and thus inherit properties like copy, move, compare, VTable, „POD-ness“. * The COR must implement the following _iteration control API:_ * -# `checkPoint` establishes if the given state element represents a valid state * -# ´iterNext` evolves this state by one step (sideeffect) - * -# `yield` realises the given state, exposing a result of type `T&` + * -# `yield` realises the given state, exposing a result reference or value * Furthermore, COR must be default-constructible in _disabled_ state * @note the resulting iterator will attempt to yield a reference to type \a T when possible; * but when the wrapped `COR::yield()` produces a value, this is passed as such, moreover @@ -671,7 +676,7 @@ namespace lib { * @see iter-explorer-test.hpp * @see iter-adaptor-test.cpp */ - template + template class IterableDecorator : public COR { @@ -687,12 +692,10 @@ namespace lib { } public: - using CoreYield = iter::CoreYield; - using _CommonT = meta::CommonResultYield; - using YieldRes = typename _CommonT::ResType; - using value_type = typename _CommonT::value_type; - using reference = typename _CommonT::reference; - using pointer = typename _CommonT::pointer; + using YieldRes = iter::CoreYield; + using value_type = typename meta::RefTraits::Value; + using reference = typename meta::RefTraits::Reference; + using pointer = typename meta::RefTraits::Pointer; /** by default, pass anything down for initialisation of the core. @@ -725,10 +728,10 @@ namespace lib { pointer operator->() const { - if constexpr (_CommonT::isRef) + if constexpr (meta::isLRef_v) return & _core().yield(); // core interface: yield else - static_assert (_CommonT::isRef, + static_assert (!sizeof(COR), "can not provide operator-> " "since iterator pipeline generates a value"); } @@ -758,17 +761,14 @@ namespace lib { /// Supporting equality comparisons of equivalent iterators (equivalent state core)... - template friend bool - operator== (IterableDecorator const& il, IterableDecorator const& ir) + operator== (IterableDecorator const& il, IterableDecorator const& ir) { return (il.empty() and ir.empty()) or (il.isValid() and ir.isValid() and il._core() == ir._core()); } - - template friend bool - operator!= (IterableDecorator const& il, IterableDecorator const& ir) + operator!= (IterableDecorator const& il, IterableDecorator const& ir) { return not (il == ir); } diff --git a/src/lib/iter-cursor.hpp b/src/lib/iter-cursor.hpp index 3fba563c0..f46190650 100644 --- a/src/lib/iter-cursor.hpp +++ b/src/lib/iter-cursor.hpp @@ -155,10 +155,10 @@ namespace lib { */ template class IterCursor - : public IterStateWrapper::value_type, iter::CursorGear> + : public IterStateWrapper> { using _Core = iter::CursorGear; - using _Parent = IterStateWrapper; + using _Parent = IterStateWrapper<_Core>; public: IterCursor() =default; diff --git a/src/lib/iter-explorer.hpp b/src/lib/iter-explorer.hpp index 585b59621..261c8737d 100644 --- a/src/lib/iter-explorer.hpp +++ b/src/lib/iter-explorer.hpp @@ -275,7 +275,7 @@ namespace lib { { using SrcRaw = typename lib::meta::Strip::Type; using SrcVal = typename meta::RefTraits>::Value; - using SrcIter = lib::IterableDecorator>; + using SrcIter = lib::IterableDecorator>; }; template diff --git a/src/lib/iter-stack.hpp b/src/lib/iter-stack.hpp index 95218ee97..cc5fad9e4 100644 --- a/src/lib/iter-stack.hpp +++ b/src/lib/iter-stack.hpp @@ -111,7 +111,7 @@ namespace lib { */ template struct IterStack - : IterStateWrapper> + : IterStateWrapper> { // using default create and copy operations @@ -186,7 +186,7 @@ namespace lib { */ template struct IterQueue - : IterStateWrapper> + : IterStateWrapper> { // using default create and copy operations diff --git a/src/lib/linked-elements.hpp b/src/lib/linked-elements.hpp index 73d0d6db4..bbc5c7e87 100644 --- a/src/lib/linked-elements.hpp +++ b/src/lib/linked-elements.hpp @@ -394,8 +394,8 @@ namespace lib { }; public: - using iterator = IterStateWrapper< N, IterationState>; - using const_iterator = IterStateWrapper; + using iterator = IterStateWrapper; + using const_iterator = IterStateWrapper; iterator begin() { return iterator (head_); } diff --git a/src/vault/gear/block-flow.hpp b/src/vault/gear/block-flow.hpp index c3740a341..db06ac3a3 100644 --- a/src/vault/gear/block-flow.hpp +++ b/src/vault/gear/block-flow.hpp @@ -441,7 +441,7 @@ namespace gear { /** Adapted storage-Extent iterator, directly exposing Epoch& */ - using EpochIter = lib::IterableDecorator; + using EpochIter = lib::IterableDecorator; /** diff --git a/src/vault/mem/extent-family.hpp b/src/vault/mem/extent-family.hpp index 3c51dac84..3c5d74966 100644 --- a/src/vault/mem/extent-family.hpp +++ b/src/vault/mem/extent-family.hpp @@ -257,7 +257,7 @@ namespace mem { /** allow transparent iteration of Extents, * with the ability to expand storage */ - using iterator = lib::IterableDecorator; + using iterator = lib::IterableDecorator; /** iterate over all the currently active Extents */ iterator begin() { return iterator{IdxLink{this, start_}}; } diff --git a/tests/library/iter-core-adapter-test.cpp b/tests/library/iter-core-adapter-test.cpp index 1659a595e..a1a50d77d 100644 --- a/tests/library/iter-core-adapter-test.cpp +++ b/tests/library/iter-core-adapter-test.cpp @@ -112,7 +112,7 @@ namespace test{ void simpleUsage() { - auto it = IterableDecorator{3}; + auto it = IterableDecorator{3}; CHECK (it); CHECK (*it == 3); ++it; @@ -130,7 +130,7 @@ namespace test{ void stateManipulation() { - auto it = IterableDecorator{}; + auto it = IterableDecorator{}; CHECK (not it); CHECK (*it == 0); ++it; @@ -166,7 +166,7 @@ namespace test{ VERIFY_ERROR (ITER_EXHAUST, cc.yield() ); VERIFY_ERROR (ITER_EXHAUST, cc.iterNext() ); - auto it = IterStateWrapper{StepDown{2}}; + auto it = IterStateWrapper{StepDown{2}}; CHECK (it); CHECK (*it == 2u); ++it; @@ -206,7 +206,7 @@ namespace test{ int yield() const { return StepDown::yield(); } }; - auto it = IterableDecorator>{2}; + auto it = IterableDecorator>{2}; CHECK (it); CHECK (*it == 2); CHECK (it.n == 2); diff --git a/tests/library/iter-explorer-test.cpp b/tests/library/iter-explorer-test.cpp index 9f9d4ebfd..e03a656e1 100644 --- a/tests/library/iter-explorer-test.cpp +++ b/tests/library/iter-explorer-test.cpp @@ -124,16 +124,16 @@ namespace test{ * @note the "state core" is not accessible from the outside */ class NumberSequence - : public IterStateWrapper + : public IterStateWrapper { public: explicit NumberSequence(uint start = 0) - : IterStateWrapper (CountDown{start}) + : IterStateWrapper{CountDown{start}} { } NumberSequence(uint start, uint end) - : IterStateWrapper (CountDown(start,end)) + : IterStateWrapper{CountDown(start,end)} { } }; diff --git a/tests/library/iter-zip-test.cpp b/tests/library/iter-zip-test.cpp index 4f8aaa628..3c58945e1 100644 --- a/tests/library/iter-zip-test.cpp +++ b/tests/library/iter-zip-test.cpp @@ -246,23 +246,13 @@ namespace test{ .transform ([&](ITup& iTup){ return mapEach (iTup, access_val); }) ; - // hold onto your hat!!! + // demonstrate the composed pipeline type... CHECK (TYPE(ii) == "IterExplorer<" "IterableDecorator<" - "tuple, " // ◁──────────────────────────────── this is the overall result type "CheckedCore<" "iter_explorer::Transformer<" // ◁──────────────────────────────── the top-layer is a Transformer (to access the value from each src-iter) "iter_explorer::BaseAdapter<" "IterableDecorator<" // ◁──────────────────────────── the product-iterator we constructed - "tuple<" // ◁──────────────────────────── ....exposing the iterator-tuple as „result“ - "IterExplorer<" // ◁───────────────────────────────── the first source iterator (directly wrapping NumIter) - "iter_explorer::BaseAdapter > >, " - "IterExplorer<" // ◁───────────────────────────────── the second source iterator (based on a STL collection) - "iter_explorer::BaseAdapter<" - "iter_explorer::StlRange&> " - "> " - "> " - ">, " "CheckedCore<" // ◁──────────────────────────── ....and using the given ProductCore as »state core« "IterZip_test::demo_construction()::ProductCore> > >, " "tuple " // ◁──────────────────────────────── back to top-layer: result-type of the Transformer diff --git a/tests/library/text-template-test.cpp b/tests/library/text-template-test.cpp index fce2f2617..ebddf0d83 100644 --- a/tests/library/text-template-test.cpp +++ b/tests/library/text-template-test.cpp @@ -461,7 +461,7 @@ for} tail... auto it = binding.getSequence("i"); CHECK (it); CHECK (*it == "i.p."_expect ); - CHECK (meta::typeStr(it) == "IterExplorer, string> > > >"_expect ); + CHECK (meta::typeStr(it) == "IterExplorer, string> > > >"_expect ); auto subBind = binding.openContext(it); CHECK (subBind.isSubScope()); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 11610ed0d..bda391fd9 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -19922,9 +19922,7 @@ - - - +

den Medien-Typ @@ -20306,9 +20304,7 @@ - - - +

Verwaltung autmatisch via ViewLocator -> PanelLocator @@ -20759,9 +20755,7 @@ - - - +

da der ViewHook schon zwei Pointer zu zwei Entitäten halten muß, kann man Redundanzen vermeiden, indem man ihn an einem dritten Ort anbringt. Nämlich an einem Ort, an dem ohnehin schon eine Dreiecksbeziehung mit diesen beiden Elementen besteht @@ -21182,9 +21176,7 @@ - - - +

alle anderen Daten in TrackBody sind nicht redundant @@ -22350,9 +22342,7 @@ - - - +

Problem: alle Timelines der Session repräsentieren? @@ -23826,9 +23816,7 @@ - - - +

  • @@ -27543,9 +27531,7 @@ - - - +

    Mitte der »Oberdiogonalen«, d.h die Diagonale durch das obere Rechteck mit Höhe Φ-major und voller Breite @@ -36550,9 +36536,7 @@ - - - +

    also kein Initialisieren des Toolkit, @@ -39610,9 +39594,7 @@ - - - +

    sonst verschleppt man eine zufällig vorher gegebene Position @@ -40906,9 +40888,7 @@ - - - +

    ...auch das basiert auf einer pragmatischen Überlegung; theoretisch könnten wir beliebig große Pixelanzahl unterstützen, dies würde aber auf allen Ebenen zu unerwartetem Verhalten führen, dessen Konsequenzen ich nicht überblicke ⟹ dann besser eine willkürliche und hinreichend große Grenze @@ -41873,9 +41853,7 @@ - - - +

    wenn der Zoom-Faktor einen größeen Nenner bekommt, wird er nach den inzwischen etablierten Richtlinien als »toxisch« betrachtet, und das heißt, die typischen Berechnungen im ZoomWindow könnten entgleisen @@ -42299,9 +42277,7 @@ - - - +

    latente Gefahr: Rest bei giftiger Duration @@ -42621,9 +42597,7 @@ - - - +

    ZoomWindow: established size or metric misses expectation by more than 1px. 3px != 0.279620 expected pixel. @@ -43018,9 +42992,7 @@ - - - +

    will sagen, wenn man das 0.1px-Band zum Absturz bringen kann, dann klappt das mit der doppelten Zeit auch beim 1px-Band @@ -52573,7 +52545,8 @@ - + + @@ -53314,7 +53287,8 @@ - + + @@ -53478,7 +53452,8 @@ - + + @@ -53489,12 +53464,13 @@ + - - - - + + + + @@ -53509,7 +53485,7 @@ - + @@ -53531,12 +53507,21 @@ - + - - + + + + + + + + + + + @@ -53549,7 +53534,7 @@ - + @@ -54353,7 +54338,7 @@ - + @@ -54633,6 +54618,24 @@ + + + + + + + + + + +

    + man muß dafür nun i.d.R. etwas coden und die (stets vorhandenen) Value-Type-Bindings extrahieren, oder meta::Yield<IT> verwenden +

    + +
    + +
    + @@ -54815,6 +54818,48 @@ + + + + + + + + + + +

    + Nebenbei bei der der Entwicklung eines tuple-zipping-Iterators; da ist mir aufgefallen, daß über weite Strecken der Ergebnistyp durchgereicht wird; einziger Knackpunkt wären Filter und Transformer, die ihre Argumente by-Ref nehmen; ich gehe aber davon aus, daß solche Funktoren ehr für den Einzelfall geschrieben sind — und in den allermeisten Fällen liefern wir ja weiterhin by-ref +

    + +
    + + + + + + + + +

    + in value-type-binding.hpp +

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