diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index 453f51f87..573410457 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -782,17 +782,22 @@ namespace lib { /** - * Accessing a STL element range through a Lumiera forward iterator, + * Access a STL element range through a »Lumiera Forward Iterator«. * An instance of this iterator adapter is completely self-contained * and allows to iterate once over the range of elements, until * `pos==end`. Thus, a custom container may expose a range of * elements of an embedded STL container, without controlling - * the details of the iteration (as is possible using the + * the details of the iteration (as would be possible using the * more generic IterAdapter). * @note - * - when IT is just a pointer, we use the pointee as value type - * - but when IT is a class, we expect the usual STL style nested typedefs - * `value_type`, `reference` and `pointer` + * - when IT is a STL iterator, we use the pointee as value type + * - but when IT is a »Lumiera Forward Iterator«, we need to evaluate + * nested typedefs `value_type`, `reference` and `pointer` + * @remark the reason for this tricky distinction is a _clash of concepts:_ + * In Lumiera, »Iterator« has a special meaning and can used on itself, + * while in the STL, an »Iterator« is a pointer in disguise and is + * only meaningful when the backing container is known. This adaptor, + * RangeIter, acts as a bridge and levels those usage styles. */ template class RangeIter @@ -800,7 +805,9 @@ namespace lib { IT p_; IT e_; - using _ValTrait = meta::ValueTypeBinding>; + static constexpr bool _is_LumieraIter = meta::can_IterForEach::value; + using _ValTrait = std::conditional_t<_is_LumieraIter, meta::ValueTypeBinding + , meta::ValueTypeBinding>>; public: using pointer = _ValTrait::pointer; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 3de7b1f7b..10582c014 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -53256,6 +53256,231 @@ + + + + + + + + +

+ Wobei mir nicht klar ist, ob das Problem grundsätzlicher Natur ist. +

+

+ Jedenfalls haben wir in den ValueTypeTraits (aber nicht in den RefTraits) eine Verzweigung, die prüft, ob nested-typedefs da sind. Wenn nicht, gehen wir in die RefTraits (d.h. wir leveln den Einstieg über Referenz oder Value). Wenn aber ja, dann nehmen wir die nested Typedefs +

+ +
+ +
+ + + + + + +
    +
  • + wir steigen ein über den RangeIter<NestedIter *>. Warum? weil im Testfall die Quelle ein Array ist, d.h. VAL* ist der "iterator" +
  • +
  • + erstes Problem ist schon mal, daß wir einen Pointer strippen. Warum habe ich das so geschrieben?  Ohne dieses Pointer-strippen würde (vermutlich) die Weiche in ValueTypeBindings niemals ansprechen können +
  • +
  • + und dann ist das andere Problem (Folgeprolem? oder die eigentliche Ursache?) daß der pointer-gestrippte Wert eben ein nested Iterator ist, d.h. die Weiche in ValueTypeBinding spricht an +
  • +
+

+ ⟹ wir bekommen bereits auf der Ebene den nested value Type, aber unser Code würde erwarten, an der Stelle einen Nested-Iterator in die Hand zu bekommen. Damit steigt die ganze weitere Typenbehandlungs-Logik aus +

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

+ commit e176e540043177b57b9dfd00ac1b1c837d689a6c +

+

+ Author: Ichthyostega <prg@ichthyostega.de> +

+

+ Date:   Sun May 21 02:15:02 2023 +0200 +

+

+ +

+

+     Library: adjust and fix semantics of nested 'value_type' binding +

+

+     +

+

+     This is a subtle and far reaching fix, which hopefully removes +

+

+     a roadblock regarding a Dispatcher pipeline: Our type rebinding +

+

+     template used to pick up nested type definitions, especially +

+

+     'value_type' and 'reference' from iterators and containers, +

+

+     took an overly simplistic approach, which was then fixed +

+

+     at various places driven by individual problems. +

+

+     +

+

+     Now: +

+

+      - value_type is conceptually the "thing" exposed by the iterator +

+

+      - and pointers are treated as simple values, and no longer linked +

+

+        to their pointee type; rather we handle the twist regarding +

+

+        STL const_iterator direcly (it defines a non const value_type, +

+

+        which is sensible from the STL point of view, but breaks our +

+

+        generic iterator wrapping mechanism) +

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

+ Obwohl diese Stelle, rein logisch betrachtet, direkt im Widerspruch steht zu dem Argument, das ich in der Commit-Message aufgeführt habe: hier behandle ich nämlich einen Pointer nicht als »einfach gegebenen Wert«, sondern versuche ihn bezüglich seines Pointee zu »interpretieren«. Das mag an der Stelle naheliegend scheinen, da man in einen RangeIter praktisch immer nur STL-container einwickelt, und die typischen Testfälle arbeiten mit einfachen Werten im Container. Für diese gibt es aber keine Weiche in den Value-Traits, und deshalb ist diese alte Logik scheinbar redundant, so nach dem Motto „kann ja nicht schaden“ +

+

+ +

+

+ Mein Bauchgefühl (oder die Erinnerung) sagt mir, daß ich an der Stelle nicht wußte, warum ich da dieses remove-ptr eingebaut hatte, mich aber erinnern konnte, daß es das Ergebnis einer extrem tückischen Situation war. Unter der Annahme, daß STL-container „ein einfacher Fall“ sind, erscheint es dann defensiv richtig, diese alte Qualifizierung mal drinnen zu lassen +

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

+ ist auch logisch: T* ist hier ein »Iterator« +

+ +
+ + + + + + + +

+ speziell hier müssen wir den Pointer strippen +

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

+ Die Beobachtung ist korrekt: ich hatte früher an der Stelle diesen Mismatch lokal gefixt, ohne ihn zu verstehen. Und diesen alten Fix habe ich mitgenommen; rein zufällig hat es sich in meinem neuen Framework „fast korrekt“ verhalten... +

+ +
+
+ + + + + + +

+ In der STL ist ein Iterator lediglich ein verkappter Pointer, und die Semantik bleibt operational. Dazu paßt, daß zwar eine convenience-Typedef "iterator" bzw. "const_iterator" gegeben ist, diese aber keinen eigenständigen Typ (Wrapper) bezeichnet, sondern nur ein Alias ist. Demnach ist es im STL-Framework nicht möglich (und auch nicht sinnvoll), für einen Iterator einen »value_type« zu defineren: Der Iterator ist stets konzeptionell an einen Container gebunden, und der Container definiert die Typen. +

+

+ +

+

+ Ganz anders in Lumiera: dort ist »Iterator« ein eigenständiges Konzept. Das geht so weit, daß »Iterator« under »Lumiera-Iterable« kongruent gemacht werden können (weil wir keinen Reset und keine Navigation erlauben). Insofern inspieriert von Python. Und weil das so ist, müssen  wir ausgehend vom Iterator nach den Typen suchen (value, reference...). Denn was anderes haben wir gar nicht in der Hand. Es gibt nicht den »eigentlichen Container«. +

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