From e176e540043177b57b9dfd00ac1b1c837d689a6c Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 21 May 2023 02:15:02 +0200 Subject: [PATCH] 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) --- src/lib/format-util.hpp | 2 +- src/lib/iter-adapter-stl.hpp | 38 +- src/lib/iter-adapter.hpp | 12 +- src/lib/iter-cursor.hpp | 6 +- src/lib/iter-source.hpp | 2 +- src/lib/iter-tree-explorer.hpp | 18 +- src/lib/itertools.hpp | 17 +- src/lib/meta/trait.hpp | 36 +- src/lib/meta/value-type-binding.hpp | 59 +-- src/lib/scoped-collection.hpp | 4 +- src/lib/test/test-helper.hpp | 7 + src/lib/wrapper.hpp | 2 +- src/steam/mobject/session/placement-index.hpp | 14 +- src/steam/mobject/session/scope-path.hpp | 2 +- .../library/meta/value-type-binding-test.cpp | 146 +++---- wiki/thinkPad.ichthyo.mm | 365 +++++++++++++++++- 16 files changed, 543 insertions(+), 187 deletions(-) diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp index 3d926e9f5..3d84cf024 100644 --- a/src/lib/format-util.hpp +++ b/src/lib/format-util.hpp @@ -133,7 +133,7 @@ namespace util { inline auto stringify (IT&& src) { - using Val = typename std::remove_reference::type::value_type; + using Val = typename lib::meta::ValueTypeBinding::value_type; return lib::transformIterator(forward(src), util::toString); } diff --git a/src/lib/iter-adapter-stl.hpp b/src/lib/iter-adapter-stl.hpp index e41e29008..cdeb411c9 100644 --- a/src/lib/iter-adapter-stl.hpp +++ b/src/lib/iter-adapter-stl.hpp @@ -58,9 +58,9 @@ namespace iter_stl { class DistinctIter { public: - typedef typename IT::value_type value_type; - typedef typename IT::reference reference; - typedef typename IT::pointer pointer; + using value_type = typename IT::value_type; + using reference = typename IT::reference; + using pointer = typename IT::pointer; private: IT i_; @@ -135,10 +135,10 @@ namespace iter_stl { template struct Wrapped_Identity { - typedef IT Iter; - typedef typename IT::value_type value_type; - typedef typename IT::reference reference; - typedef typename IT::pointer pointer; + using Iter = IT; + using value_type = typename IT::value_type; + using reference = typename IT::reference; + using pointer = typename IT::pointer; static Iter get (Iter& it) { return & (*it); } }; @@ -150,10 +150,10 @@ namespace iter_stl { template struct Wrapped_PickKey { - typedef IT Iter; - typedef typename IT::value_type::first_type value_type; - typedef value_type & reference; - typedef value_type * pointer; + using Iter = IT; + using value_type = typename IT::value_type::first_type; + using reference = value_type &; + using pointer = value_type *; static pointer get (Iter& it) { return & (it->first); } }; @@ -165,10 +165,10 @@ namespace iter_stl { template struct Wrapped_PickVal { - typedef IT Iter; - typedef typename IT::value_type::second_type value_type; - typedef value_type & reference; - typedef value_type * pointer; + using Iter = IT; + using value_type = typename IT::value_type::second_type; + using reference = value_type &; + using pointer = value_type *; static pointer get (Iter& it) { return & (it->second); } }; @@ -176,10 +176,10 @@ namespace iter_stl { template struct Wrapped_PickConstVal { - typedef IT Iter; - typedef typename IT::value_type::second_type value_type; - typedef value_type const& reference; - typedef value_type const* pointer; + using Iter = IT; + using value_type = const typename IT::value_type::second_type; + using reference = const value_type &; + using pointer = const value_type *; static pointer get (Iter& it) { return & (it->second); } }; diff --git a/src/lib/iter-adapter.hpp b/src/lib/iter-adapter.hpp index 1364c36d5..0fadc0a5f 100644 --- a/src/lib/iter-adapter.hpp +++ b/src/lib/iter-adapter.hpp @@ -174,7 +174,7 @@ namespace lib { CON source_; mutable POS pos_; - using _ValTrait = meta::TypeBinding>; + using _ValTrait = meta::ValueTypeBinding>; public: using value_type = typename _ValTrait::value_type; @@ -267,7 +267,7 @@ namespace lib { protected: - using ConRef = typename meta::TypeBinding::reference; + using ConRef = typename meta::RefTraits::Reference; /** allow derived classes to access backing container */ ConRef source() { return source_; } @@ -471,12 +471,14 @@ namespace lib { IT p_; IT e_; - using _ValTrait = meta::TypeBinding>; + using _ValTrait = meta::ValueTypeBinding>; public: - using value_type = typename _ValTrait::value_type; - using reference = typename _ValTrait::reference; using pointer = typename _ValTrait::pointer; + using reference = typename _ValTrait::reference; + + /// @note special twist, since a STL const_iterator would yield a non-const `value_type` + using value_type = typename std::remove_reference::type; RangeIter (IT const& start, IT const& end) diff --git a/src/lib/iter-cursor.hpp b/src/lib/iter-cursor.hpp index 013ed975e..e358f0a71 100644 --- a/src/lib/iter-cursor.hpp +++ b/src/lib/iter-cursor.hpp @@ -65,9 +65,9 @@ namespace lib { public: - typedef typename meta::TypeBinding::pointer pointer; - typedef typename meta::TypeBinding::reference reference; - typedef typename std::remove_reference::type value_type; ///< @note will be const for const iterators + using pointer = typename meta::ValueTypeBinding::pointer; + using reference = typename meta::ValueTypeBinding::reference; + using value_type = typename std::remove_reference::type; ///< @note will be const for const iterators (while const_iterator::value_type isn't) CursorGear() diff --git a/src/lib/iter-source.hpp b/src/lib/iter-source.hpp index b20a9ad49..b3180766b 100644 --- a/src/lib/iter-source.hpp +++ b/src/lib/iter-source.hpp @@ -229,7 +229,7 @@ namespace lib { * is passed to one of the IterSource's builder functions, thereby * erasing the specific type information of the template parameter IT */ - template> + template::value_type>> class WrappedLumieraIter : public ISO , util::NonCopyable diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 14b378835..edd579d00 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -388,9 +388,9 @@ namespace lib { { using Res = remove_reference_t().yield())>; - using value_type = typename meta::TypeBinding::value_type; - using reference = typename meta::TypeBinding::reference; - using pointer = typename meta::TypeBinding::pointer; + using value_type = typename meta::ValueTypeBinding::value_type; + using reference = typename meta::ValueTypeBinding::reference; + using pointer = typename meta::ValueTypeBinding::pointer; }; @@ -846,9 +846,9 @@ namespace lib { TransformedItem treated_; public: - using value_type = typename meta::TypeBinding::value_type; - using reference = typename meta::TypeBinding::reference; - using pointer = typename meta::TypeBinding::pointer; + using value_type = typename meta::ValueTypeBinding::value_type; + using reference = typename meta::ValueTypeBinding::reference; + using pointer = typename meta::ValueTypeBinding::pointer; Transformer() =default; @@ -1347,9 +1347,9 @@ namespace lib { public: - using value_type = typename meta::TypeBinding::value_type; - using reference = typename meta::TypeBinding::reference; - using pointer = typename meta::TypeBinding::pointer; + using value_type = typename meta::ValueTypeBinding::value_type; + using reference = typename meta::ValueTypeBinding::reference; + using pointer = typename meta::ValueTypeBinding::pointer; /** pass-through ctor */ using SRC::SRC; diff --git a/src/lib/itertools.hpp b/src/lib/itertools.hpp index d20e53a69..1b52f7c7b 100644 --- a/src/lib/itertools.hpp +++ b/src/lib/itertools.hpp @@ -95,7 +95,7 @@ namespace lib { using std::function; using util::unConst; - using lib::meta::TypeBinding; + using lib::meta::ValueTypeBinding; @@ -754,9 +754,9 @@ namespace lib { return bool(source_); } - typedef typename TypeBinding::pointer pointer; - typedef typename TypeBinding::reference reference; - typedef typename TypeBinding::value_type value_type; + using pointer = typename ValueTypeBinding::pointer; + using reference = typename ValueTypeBinding::reference; + using value_type = typename ValueTypeBinding::value_type; }; @@ -833,8 +833,8 @@ namespace lib { inline typename IT::value_type pull_last (IT iter) { - typedef typename IT::value_type Val; - typedef wrapper::ItemWrapper Item; + using Val = typename IT::value_type; + using Item = wrapper::ItemWrapper; Item lastElm; @@ -860,7 +860,7 @@ namespace lib { inline auto filterRepetitions (IT const& source) { - using Val = typename IT::value_type; + using Val = typename meta::ValueTypeBinding::value_type; return filterIterator (source, SkipRepetition()); } @@ -868,8 +868,7 @@ namespace lib { inline auto filterRepetitions (IT&& source) { - using SrcIT = typename std::remove_reference::type; - using Val = typename SrcIT::value_type; + using Val = typename meta::ValueTypeBinding::value_type; return filterIterator (forward(source), SkipRepetition() ); } diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index bd93801da..b65dba404 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -94,8 +94,11 @@ namespace lib { namespace meta { using std::remove_cv; + using std::remove_cv_t; using std::remove_pointer; + using std::remove_pointer_t; using std::remove_reference; + using std::remove_reference_t; using std::is_pointer; using std::is_base_of; using std::is_convertible; @@ -257,37 +260,40 @@ namespace meta { /** Type definition helper for pointer and reference types. * Allows to create a member field and to get the basic type * irrespective if the given type is plain, pointer or reference + * @note we _do treat pointers specific_ though; a pointer is itself + * a value and the pointer-indirection is _not_ stripped. + * (use meta::Strip to radically strip all adornments) */ template struct RefTraits { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; + typedef TY Value; + typedef TY* Pointer; + typedef TY& Reference; }; template struct RefTraits { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; + typedef TY* Value; + typedef TY** Pointer; + typedef TY*& Reference; }; template struct RefTraits { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; + typedef TY Value; + typedef TY* Pointer; + typedef TY& Reference; }; template struct RefTraits { - typedef TY* pointer; - typedef TY& reference; - typedef TY value_type; + typedef TY Value; + typedef TY* Pointer; + typedef TY& Reference; }; @@ -474,7 +480,7 @@ namespace meta { template class can_IterForEach { - typedef typename Strip::Type Type; + using Type = typename Strip::Type; META_DETECT_NESTED(value_type); META_DETECT_OPERATOR_DEREF(); @@ -496,7 +502,7 @@ namespace meta { template class can_STL_ForEach { - typedef typename Strip::Type Type; + using Type = typename Strip::Type; struct is_iterable { @@ -560,7 +566,7 @@ namespace meta { template class can_STL_backIteration { - typedef typename Strip::Type Type; + using Type = typename Strip::Type; struct is_backIterable { diff --git a/src/lib/meta/value-type-binding.hpp b/src/lib/meta/value-type-binding.hpp index ce5f4b12a..d5e263a99 100644 --- a/src/lib/meta/value-type-binding.hpp +++ b/src/lib/meta/value-type-binding.hpp @@ -36,7 +36,7 @@ ** Within the STL, there is a convention to provide nested typedefs to indicate ** type variations in relation to the basic payload type of the container. We ** follow this convention and support especially the - ** - `value_type` + ** - `value_type` (what is conceived to be "in" the container or iterator) ** - a simple (LValue) reference to the payload ** - a pointer at the payload. ** @@ -47,6 +47,7 @@ ** treatment, an explicit specialisation to this rebinding trait may be ** injected alongside with the definition of the payload type. ** + ** @see ValueTypeBinding_test ** @see iter-adapter.hpp ** @see scope-path.hpp usage example (explicit specialisation) */ @@ -88,39 +89,17 @@ namespace meta { template struct use_ValueTypebindings - : __and_ - ,__not_ + : __and_ > + ,__not_ > > > { }; } - /** - * @internal helper template to pick up nested value type definitions - */ - template - struct ValueTypeBinding - { - typedef TY value_type; - typedef TY& reference; - typedef TY* pointer; - }; - - /** specialisation for classes providing STL style type binding definitions */ - template - struct ValueTypeBinding> > - { - typedef typename TY::value_type value_type; - typedef typename TY::reference reference; - typedef typename TY::pointer pointer; - }; - - - /** * Type re-binding helper template for creating nested typedefs - * for use by custom containers and iterator adapters or similar. + * usable by custom containers and iterator adapters or similar. * - this trait provides a value-, reference- and pointer type, * similar to what the STL does. * - references are stripped, otherwise the base type is passed through @@ -129,20 +108,24 @@ namespace meta { * @note client code might define specialisations * to handle tricky situations (like e.g. const_reverse_iter) */ - template - struct TypeBinding - : ValueTypeBinding - { }; + template + struct ValueTypeBinding + { + using value_type = typename RefTraits::Value; + using reference = typename RefTraits::Reference; + using pointer = typename RefTraits::Pointer; + }; + /** specialisation for classes providing STL style type binding definitions */ template - struct TypeBinding - : TypeBinding - { }; - - template - struct TypeBinding - : TypeBinding - { }; + struct ValueTypeBinding> > + { + using _SrcType = typename RefTraits::Value; + + using value_type = typename _SrcType::value_type; + using reference = typename _SrcType::reference; + using pointer = typename _SrcType::pointer; + }; diff --git a/src/lib/scoped-collection.hpp b/src/lib/scoped-collection.hpp index 7300fece2..4be262287 100644 --- a/src/lib/scoped-collection.hpp +++ b/src/lib/scoped-collection.hpp @@ -452,7 +452,7 @@ namespace lib { * This variant allows to "pull" elements from an iterator. * Actually, the collection will try to create each element right away, * by invoking the copy ctor and passing the value yielded by the iterator. - * @note anything in accordance to the Lumera Forward Iterator pattern is OK. + * @note anything in accordance to the Lumiera Forward Iterator pattern is OK. * This rules out just passing a plain STL iterator (because these can't * tell for themselves when they're exhausted). Use an suitable iter-adapter * instead, e.g. by invoking lib::iter_stl::eachElm(stl_container) @@ -463,7 +463,7 @@ namespace lib { { IT iter_; - typedef typename meta::TypeBinding::value_type ElementType; + using ElementType = typename meta::ValueTypeBinding::value_type; public: PullFrom (IT source) diff --git a/src/lib/test/test-helper.hpp b/src/lib/test/test-helper.hpp index c3f1e0bb2..7bba668f2 100644 --- a/src/lib/test/test-helper.hpp +++ b/src/lib/test/test-helper.hpp @@ -166,6 +166,13 @@ namespace test{ static constexpr auto postfix = ""; }; template + struct TypeDiagnostics + { + using Type = X; + static constexpr auto prefix = "const "; + static constexpr auto postfix = ""; + }; + template struct TypeDiagnostics { using Type = X; diff --git a/src/lib/wrapper.hpp b/src/lib/wrapper.hpp index 363274fb6..8be230728 100644 --- a/src/lib/wrapper.hpp +++ b/src/lib/wrapper.hpp @@ -303,7 +303,7 @@ namespace wrapper { /** * Specialisation of the ItemWrapper to deal with references, * as if they were pointer values. Allows the reference value - * to be default constructed to `NULL` and to be re-assigned. + * to be default constructed to ⟂ (invalid) and to be re-assigned. */ template class ItemWrapper diff --git a/src/steam/mobject/session/placement-index.hpp b/src/steam/mobject/session/placement-index.hpp index a5bf47d29..31c642609 100644 --- a/src/steam/mobject/session/placement-index.hpp +++ b/src/steam/mobject/session/placement-index.hpp @@ -185,18 +185,18 @@ namespace session { unique_ptr pTab_; - typedef PlacementMO::ID _PID; - typedef std::unordered_multimap<_PID,_PID>::const_iterator ScopeIter; - typedef lib::RangeIter ScopeRangeIter; - typedef lib::TransformIter _ID_TableIterator; + using _PID = PlacementMO::ID; + using ScopeIter = std::unordered_multimap<_PID,_PID>::const_iterator; + using ScopeRangeIter = lib::RangeIter; + using _ID_TableIterator = lib::TransformIter; public: - typedef PlacementRef PRef; - typedef PlacementMO::ID const& ID; + using PRef = PlacementRef; + using ID = PlacementMO::ID const&; - typedef _ID_TableIterator iterator; + using iterator = _ID_TableIterator; /* == query operations == */ diff --git a/src/steam/mobject/session/scope-path.hpp b/src/steam/mobject/session/scope-path.hpp index 7950eb489..c140ada87 100644 --- a/src/steam/mobject/session/scope-path.hpp +++ b/src/steam/mobject/session/scope-path.hpp @@ -109,7 +109,7 @@ namespace meta{ * @see iter-adapter.hpp */ template<> - struct TypeBinding::const_reverse_iterator> + struct ValueTypeBinding::const_reverse_iterator> { typedef const Scope value_type; typedef Scope const& reference; diff --git a/tests/library/meta/value-type-binding-test.cpp b/tests/library/meta/value-type-binding-test.cpp index e7eefa314..462e58716 100644 --- a/tests/library/meta/value-type-binding-test.cpp +++ b/tests/library/meta/value-type-binding-test.cpp @@ -84,103 +84,103 @@ namespace test{ run (Arg) { // verify the type diagnostics helper... - CHECK ("int" == showType() ); - CHECK ("int&" == showType() ); - CHECK ("int &&" == showType() ); - CHECK ("int const&" == showType() ); - CHECK ("const int &&" == showType() ); - CHECK ("int *" == showType() ); - CHECK ("const int *" == showType() ); - CHECK ("const int * const" == showType() ); - CHECK ("int const*&" == showType() ); - CHECK ("int const* const&" == showType() ); + CHECK (showType() == "int"_expect ); + CHECK (showType() == "int&"_expect ); + CHECK (showType() == "int &&"_expect ); + CHECK (showType() == "int const&"_expect ); + CHECK (showType() == "const int &&"_expect ); + CHECK (showType() == "int *"_expect ); + CHECK (showType() == "const int *"_expect ); + CHECK (showType() == "const int * const"_expect ); + CHECK (showType() == "int const*&"_expect ); + CHECK (showType() == "int const* const&"_expect ); // Test fixture: the template Outer provides nested value type bindings - using OuterSpace = Outer; - using Join = ulong; + CHECK (showType::value_type>() == "Space"_expect ); + CHECK (showType::reference>() == "Outer::Inner&"_expect ); + CHECK (showType::pointer>() == "shared_ptr"_expect ); - CHECK ("Space" == showType() ); - CHECK ("Outer::Inner&" == showType() ); - CHECK ("shared_ptr" == showType() ); // ...such nested type bindings will be picked up - CHECK ("Space" == showType::value_type>() ); - CHECK ("Outer::Inner&" == showType::reference>() ); - CHECK ("shared_ptr" == showType::pointer>() ); + CHECK (showType>::value_type>() == "Space"_expect ); + CHECK (showType>::reference>() == "Outer::Inner&"_expect ); + CHECK (showType>::pointer>() == "shared_ptr"_expect ); - CHECK ("unsigned long" == showType>::value_type>() ); - CHECK ("Outer::Inner&" == showType>::reference>() ); - CHECK ("shared_ptr" == showType>::pointer>() ); + CHECK (showType>::value_type>() == "short"_expect ); + CHECK (showType>::reference>() == "Outer::Inner&"_expect ); + CHECK (showType>::pointer>() == "shared_ptr"_expect ); // contrast this to a type without such nested bindings - CHECK ("Space" == showType::value_type>() ); - CHECK ("Space&" == showType::reference>() ); - CHECK ("Space *" == showType::pointer>() ); + CHECK (showType::value_type>() == "Space"_expect ); + CHECK (showType::reference>() == "Space&"_expect ); + CHECK (showType::pointer>() == "Space *"_expect ); - // reference types will be levelled (reference stripped) - CHECK ("Space" == showType::value_type>() ); - CHECK ("Outer::Inner&" == showType::reference>() ); - CHECK ("shared_ptr" == showType::pointer>() ); + // when checking for nested bindings, reference will be stripped and just the binding returned as-is + CHECK (showType&>::_SrcType>() == "Outer"_expect ); // internal: this is the type probed for nested bindings + CHECK (showType&>::value_type>() == "Space"_expect ); + CHECK (showType&>::reference>() == "Outer::Inner&"_expect ); + CHECK (showType&>::pointer>() == "shared_ptr"_expect ); - CHECK ("Space" == showType::value_type>() ); - CHECK ("Outer::Inner&" == showType::reference>() ); - CHECK ("shared_ptr" == showType::pointer>() ); + CHECK (showType&&>::_SrcType>() == "Outer"_expect ); // likewise for && + CHECK (showType&&>::value_type>() == "Space"_expect ); + CHECK (showType&&>::reference>() == "Outer::Inner&"_expect ); + CHECK (showType&&>::pointer>() == "shared_ptr"_expect ); - CHECK ("Space" == showType::value_type>() ); - CHECK ("Outer::Inner&" == showType::reference>() ); - CHECK ("shared_ptr" == showType::pointer>() ); + CHECK (showType const&>::value_type>() == "Space"_expect ); + CHECK (showType const&>::reference>() == "Outer::Inner&"_expect ); + CHECK (showType const&>::pointer>() == "shared_ptr"_expect ); - // but a pointer counts as a different, primitive type. No magic here - CHECK ("Outer *" == showType::value_type>() ); - CHECK ("Outer*&" == showType::reference>() ); - CHECK ("Outer* *" == showType::pointer>() ); + // but a pointer counts as different, primitive type. No magic here + CHECK (showType * >::value_type>() == "Outer *"_expect ); + CHECK (showType * >::reference>() == "Outer*&"_expect ); + CHECK (showType * >::pointer>() == "Outer* *"_expect ); - CHECK ("const Outer *" == showType::value_type>() ); - CHECK ("Outer const*&" == showType::reference>() ); - CHECK ("Outer const* *" == showType::pointer>() ); + CHECK (showType * >::value_type>() == "const Outer *"_expect ); + CHECK (showType * >::reference>() == "Outer const*&"_expect ); + CHECK (showType * >::pointer>() == "Outer const* *"_expect ); - CHECK ("const Outer * const" == showType::value_type>() ); - CHECK ("Outer const* const&" == showType::reference>() ); - CHECK ("Outer * const *" == showType::pointer>() ); + CHECK (showType * const>::value_type>() == "const Outer * const"_expect ); + CHECK (showType * const>::reference>() == "Outer const* const&"_expect ); + CHECK (showType * const>::pointer>() == "Outer * const *"_expect ); - CHECK ("Outer * const" == showType::value_type>() ); - CHECK ("Outer* const&" == showType::reference>() ); - CHECK ("Outer * const *" == showType::pointer>() ); + CHECK (showType * const>::value_type>() == "Outer * const"_expect ); + CHECK (showType * const>::reference>() == "Outer* const&"_expect ); + CHECK (showType * const>::pointer>() == "Outer * const *"_expect ); - // similar for a type without nested type bindings: references are levelled - CHECK ("unsigned long" == showType::value_type>() ); - CHECK ("unsigned long&" == showType::reference>() ); - CHECK ("unsigned long *" == showType::pointer>() ); + // yet for a type without nested type bindings: references are levelled + CHECK (showType::value_type>() == "short"_expect ); + CHECK (showType::reference>() == "short&"_expect ); + CHECK (showType::pointer>() == "short *"_expect ); - CHECK ("unsigned long" == showType::value_type>() ); - CHECK ("unsigned long&" == showType::reference>() ); - CHECK ("unsigned long *" == showType::pointer>() ); + CHECK (showType::value_type>() == "short"_expect ); + CHECK (showType::reference>() == "short&"_expect ); + CHECK (showType::pointer>() == "short *"_expect ); - CHECK ("unsigned long" == showType::value_type>() ); - CHECK ("unsigned long&" == showType::reference>() ); - CHECK ("unsigned long *" == showType::pointer>() ); - - CHECK ("unsigned long" == showType::value_type>() ); - CHECK ("unsigned long const&" == showType::reference>() ); - CHECK ("const unsigned long *" == showType::pointer>() ); + CHECK (showType::value_type>() == "short"_expect ); + CHECK (showType::reference>() == "short&"_expect ); + CHECK (showType::pointer>() == "short *"_expect ); + + CHECK (showType::value_type>() == "const short"_expect ); + CHECK (showType::reference>() == "short const&"_expect ); + CHECK (showType::pointer>() == "const short *"_expect ); //... but pointer types are not treated special in any way - CHECK ("unsigned long *" == showType::value_type>() ); - CHECK ("unsigned long*&" == showType::reference>() ); - CHECK ("unsigned long* *" == showType::pointer>() ); + CHECK (showType::value_type>() == "short *"_expect ); + CHECK (showType::reference>() == "short*&"_expect ); + CHECK (showType::pointer>() == "short* *"_expect ); - CHECK ("const unsigned long *" == showType::value_type>() ); - CHECK ("unsigned long const*&" == showType::reference>() ); - CHECK ("unsigned long const* *" == showType::pointer>() ); + CHECK (showType::value_type>() == "const short *"_expect ); + CHECK (showType::reference>() == "short const*&"_expect ); + CHECK (showType::pointer>() == "short const* *"_expect ); - CHECK ("const unsigned long * const" == showType::value_type>() ); - CHECK ("unsigned long const* const&" == showType::reference>() ); - CHECK ("unsigned long * const *" == showType::pointer>() ); + CHECK (showType::value_type>() == "const short * const"_expect ); + CHECK (showType::reference>() == "short const* const&"_expect ); + CHECK (showType::pointer>() == "short * const *"_expect ); - CHECK ("unsigned long * const" == showType::value_type>() ); - CHECK ("unsigned long* const&" == showType::reference>() ); - CHECK ("unsigned long * const *" == showType::pointer>() ); + CHECK (showType::value_type>() == "short * const"_expect ); + CHECK (showType::reference>() == "short* const&"_expect ); + CHECK (showType::pointer>() == "short * const *"_expect ); } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index e7c350cb3..5c5f36783 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -70480,7 +70480,25 @@ - + + + + + + + + + + + +

+ ...für die STL schon, aber das ist genau meine Kritik: die STL ist hier zu konkret und zu sehr low-level — ein const_iterator ist demnach etwas Anderes als ein iterator von einem Container über const-Werte, und das widerspricht meinem Konzept, einen Iterator als eine opaque Quelle zu betrachten +

+ +
+ +
+
@@ -70579,14 +70597,14 @@ - +

- ...was wohl genau daran liegt, daß TypeBinding konzeptionell "daneben" ist + ...was wohl genau daran liegt, daß das TypeBinding bisher konzeptionell "daneben" war

@@ -70676,6 +70694,347 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+       using              _PID = PlacementMO::ID; +

+

+       using         ScopeIter = std::unordered_multimap<_PID,_PID>::const_iterator; +

+

+       using    ScopeRangeIter = lib::RangeIter<ScopeIter>; +

+

+       using _ID_TableIterator = lib::TransformIter<ScopeRangeIter, PlacementMO&>; +

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

+ TransformIter<RangeIter<__normal_iterator<const GenNode*, vector<GenNode> > > +

+

+              ,JobTicket& +

+

+              > +

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

+ Hatte zunächst gedacht, generell sollte value_type den Typparameter unverändert durchreichen (sofern kein nested Binding erfolgt). Tatsächlich bestand das Problem aber nur bei Pointern, und das lösen wir besser direkt in den RefTraits +

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

+ IterAdapter selber sieht sauber aus.... +

+ +
+ + + + + + + + +

+ und im Besonderen kein automatisches Entfernen von Indirektionen, und kein Rückgriff auf interne Typdefinitionen (also grade nicht  ValueTypeBinding verwenden!) +

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

+    * @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` +

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

+ das heißt, wir erkennen gar nicht mehr, daß der Typ möglicherweise nested Bindings hat, weil viele Konstrukte für Klassen gar nicht valide sind für Referenzen, und daher die Erkennungs-Mechanismen ins Leer laufen +

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