Library: further clean-up of type definitions related to iterators
More documentation and occasional rearrangements made as an aside of debugging issues around handling of Lumiera iterators vs. STL iterators...
This commit is contained in:
parent
f05402c04e
commit
0326f9e85d
9 changed files with 258 additions and 63 deletions
|
|
@ -376,7 +376,7 @@ namespace lib {
|
|||
using ResultVal = meta::_Fun<FUN>::Ret;
|
||||
using Subclass = meta::Strip<ResultVal>::TypePlain;
|
||||
|
||||
static_assert (std::is_pointer<ResultVal>::value,
|
||||
static_assert (std::is_pointer_v<ResultVal>,
|
||||
"Function must yield a pointer to a heap allocated instance");
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -776,7 +776,7 @@ namespace diff{
|
|||
inline std::optional<X>
|
||||
DataCap::retrieveAttribute (string key) const
|
||||
{
|
||||
static_assert (not std::is_reference_v<X>
|
||||
static_assert (not meta::isRef_v<X>
|
||||
,"optional access only possible by value");
|
||||
|
||||
Rec* nested = unConst(this)->maybeAccessNestedRec();
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace lib {
|
|||
public:
|
||||
/** this iterator adapter is meant to wrap an iterator yielding pointer values */
|
||||
using pointer = meta::ValueTypeBinding<IT>::value_type;
|
||||
static_assert(std::is_pointer_v<pointer>);
|
||||
static_assert(is_pointer_v<pointer>);
|
||||
|
||||
using value_type = std::remove_pointer_t<pointer>;
|
||||
using reference = value_type&;
|
||||
|
|
@ -74,8 +74,8 @@ namespace lib {
|
|||
|
||||
using ValueTypeBase = std::remove_const_t<value_type>; // value_type without const
|
||||
|
||||
using WrappedIterType = IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type;
|
||||
using WrappedConstIterType = IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type;
|
||||
using WrappedIterType = IterRebind<IT>::template SimilarIter< ValueTypeBase* * >::Type;
|
||||
using WrappedConstIterType = IterRebind<IT>::template SimilarIter<const ValueTypeBase* * >::Type;
|
||||
|
||||
using IterType = PtrDerefIter<WrappedIterType>;
|
||||
using ConstIterType = PtrDerefIter<WrappedConstIterType>;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@
|
|||
** - very similar is IterableDecorator, but this time directly as
|
||||
** decorator to inherit from the »state core«, and without checks.
|
||||
** - the RangeIter allows just to expose a range of elements defined
|
||||
** by a STL-like pair of "start" and "end" iterators
|
||||
** by a STL-like pair of "start" and "end" iterators; thus it
|
||||
** serves a bridge between STL iterators and Lumiera iterators.
|
||||
**
|
||||
** Some more specific use cases are provided in the extension header
|
||||
** iter-adapter-ptr-deref.hpp
|
||||
|
|
@ -62,14 +63,14 @@
|
|||
** Similar to the STL, instead of using a common "Iterator" base class,
|
||||
** we rather define a common set of functions and behaviour which can be
|
||||
** expected from any such iterator. These rules are similar to STL's
|
||||
** "forward iterator", with the addition of an bool check to detect
|
||||
** iteration end. The latter is inspired by the \c hasNext() function
|
||||
** "input iterator", with the addition of an bool check to detect
|
||||
** iteration end. The latter is inspired by the `hasNext()` function
|
||||
** found in many current languages supporting iterators. However, by
|
||||
** inspiration from functional programming, we deliberately do not
|
||||
** support the various extended iterator concepts from STL and boost
|
||||
** drawing from insights promoted in functional programming, deliberately
|
||||
** we do not support the various extended iterator concepts from the STL
|
||||
** (random access iterators, output iterators, arithmetics, difference
|
||||
** between iterators and the like). According to this concept,
|
||||
** _an iterator is a promise for pulling values once,_
|
||||
** between iterators and the like). According to this concept proposed
|
||||
** here, _an iterator is a promise for pulling values once,_
|
||||
** and nothing beyond that.
|
||||
**
|
||||
** Notably,
|
||||
|
|
@ -87,10 +88,48 @@
|
|||
** Conceptually, a Lumiera Iterator represents a lazy stream of calculations
|
||||
** rather than a target value considered to be »within« a container. And while
|
||||
** the result is in may cases deliberately _exposed as a reference,_ in order
|
||||
** to keep the door open for special-case manipulations, for the typical usage
|
||||
** it is _discouraged_ to assume anything about the source, beyond the limited
|
||||
** access to some transient state as exposed during active iteration. Together,
|
||||
** these rules enable a _loose coupling_ to the source of data.
|
||||
** to allow for tightly coupled implementation in special cases -- for the
|
||||
** typical usage it is _discouraged_ to assume anything about the source,
|
||||
** beyond the limited access to some transient state as exposed during
|
||||
** active iteration. Together, these rules enable a _loose coupling_
|
||||
** to the source of data.
|
||||
**
|
||||
** ## Usage
|
||||
**
|
||||
** All the building blocks defined her provide the bridge definitions to allow
|
||||
** using a »Lumiera Forward Iterator« in common language constructs: It can be
|
||||
** used directly in for-each loops (notably this implies that a Lumiera iterator
|
||||
** is used in the same position where usually the container would be referred).
|
||||
** Yet, beyond that, Lumiera iterators can also be used in normal `for` loops
|
||||
** and even in while loops, due to the bool-check to detect iteration end.
|
||||
** A default constructed Lumiera iterator is always in _invalid state_
|
||||
** and can be used as _sentinel value_ like the `end()` iterator.
|
||||
** Yet, while Lumiera iterators can be copied and assigned, the effect of
|
||||
** these operations is implementation defined; in some cases, taking a copy
|
||||
** may allow to create a snapshot, while in other cases (especially when the
|
||||
** Lumiera iterator uses an reference to tap into some remote service) all
|
||||
** copies will refer to the same shared state. The rationale for this design
|
||||
** was to simplify both building and using Lumiera Iterators; they are meant
|
||||
** as an implementation tool, and not for creating external interfaces.
|
||||
**
|
||||
** However, there is a special provision for the latter use case, in the form
|
||||
** of the lib::IterSource interface and framework; an `IterSource` embeds a
|
||||
** classic OO interface with virtual methods, and thus allows to abstract the
|
||||
** backing implementation entirely away.
|
||||
**
|
||||
** ## Concepts and Traits
|
||||
**
|
||||
** The »Lumiera Forward Iterators« do not map directly to any specification from
|
||||
** the C++ standard. The concept std::input_iterator comes close, but a Lumiera
|
||||
** iterator can not fulfil this concept, since it lacks the postfix increment.
|
||||
** In the opposite direction, there is also no subsumption possible, since a
|
||||
** STL iterator does not offer a bool-check to detect iteration end.
|
||||
**
|
||||
** Notably the header `lib/meta/trait.hpp` defines some detector traits, allowing
|
||||
** to recognise if something is an iterable STL container, or a Lumiera iterator.
|
||||
** Furthermore, lib::iter::Trait defines a transparent mechanism to extract the
|
||||
** basic type definitions (`reference` ≙ what the iterator yields and
|
||||
** `value_type` ≙ what to use to store results from an iterator)
|
||||
**
|
||||
** @see iter-adapter-test.cpp
|
||||
** @see itertools.hpp
|
||||
|
|
@ -187,7 +226,7 @@ namespace lib {
|
|||
static constexpr bool is_LumieraIter = can_IterForEach<IT>::value;
|
||||
static constexpr bool is_STLIter = stl_iter<IT>;
|
||||
|
||||
// static_assert(is_LumieraIter or is_STLIter);
|
||||
static_assert(is_LumieraIter or is_STLIter, "source type must be an iterator");
|
||||
|
||||
using _ValTrait = std::conditional_t<is_LumieraIter, ValueTypeBinding<IT>
|
||||
, RefTraits<std::iter_reference_t<IT>>>;
|
||||
|
|
@ -822,13 +861,14 @@ namespace lib {
|
|||
/**
|
||||
* 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
|
||||
* 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 would be possible using the
|
||||
* more generic IterAdapter).
|
||||
* @note
|
||||
* - when IT is a STL iterator, we use the pointee as value type
|
||||
* - when IT is a STL iterator, we rely on the iterator concepts and
|
||||
* especially on `std::iter_reference_t` to find the `reference_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:_
|
||||
|
|
@ -846,9 +886,7 @@ namespace lib {
|
|||
public:
|
||||
using pointer = iter::Trait<IT>::pointer;
|
||||
using reference = iter::Trait<IT>::reference;
|
||||
|
||||
/// @note special twist, since a STL const_iterator would yield a non-const `value_type`
|
||||
using value_type = std::remove_reference_t<reference>;
|
||||
using value_type = iter::Trait<IT>::value_type;
|
||||
|
||||
|
||||
RangeIter (IT const& start, IT const& end)
|
||||
|
|
@ -1068,13 +1106,13 @@ namespace lib {
|
|||
|
||||
/**
|
||||
* Helper for type rewritings:
|
||||
* get the element type for an iterator like entity
|
||||
* build a similar iterator with another value type
|
||||
*/
|
||||
template<class TY>
|
||||
struct IterType;
|
||||
struct IterRebind;
|
||||
|
||||
template<template<class,class> class Iter, class TY, class CON>
|
||||
struct IterType<Iter<TY,CON>>
|
||||
struct IterRebind<Iter<TY,CON>>
|
||||
{
|
||||
using Container = CON;
|
||||
using ElemType = TY ;
|
||||
|
|
@ -1087,13 +1125,13 @@ namespace lib {
|
|||
};
|
||||
|
||||
template<class IT>
|
||||
struct IterType<RangeIter<IT>>
|
||||
: IterType<IT>
|
||||
struct IterRebind<RangeIter<IT>>
|
||||
: IterRebind<IT>
|
||||
{
|
||||
template<class T2>
|
||||
struct SimilarIter ///< rebind to rewritten Iterator wrapped into RangeIter
|
||||
{
|
||||
using WrappedIter = IterType<IT>::template SimilarIter<T2>::Type;
|
||||
using WrappedIter = IterRebind<IT>::template SimilarIter<T2>::Type;
|
||||
using Type = RangeIter<WrappedIter>;
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1908,7 +1908,7 @@ namespace lib {
|
|||
asPtr()
|
||||
{
|
||||
using Val = meta::ValueTypeBinding<SRC>::value_type;
|
||||
static_assert (not std::is_pointer_v<Val>);
|
||||
static_assert (not is_pointer_v<Val>);
|
||||
return IterExplorer::transform ([](Val& ref){ return &ref; });
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,9 +87,7 @@ namespace meta {
|
|||
using std::remove_pointer_t;
|
||||
using std::remove_reference_t;
|
||||
using std::conditional_t;
|
||||
using std::is_reference_v;
|
||||
using std::is_lvalue_reference_v;
|
||||
using std::is_rvalue_reference_v;
|
||||
using std::is_pointer_v;
|
||||
using std::is_pointer;
|
||||
using std::is_base_of;
|
||||
using std::is_convertible;
|
||||
|
|
@ -233,8 +231,8 @@ namespace meta {
|
|||
template<typename X>
|
||||
struct Strip
|
||||
{
|
||||
using TypeUnconst = conditional_t<is_reference_v<X>
|
||||
, conditional_t<is_rvalue_reference_v<X>
|
||||
using TypeUnconst = conditional_t<isRef_v<X>
|
||||
, conditional_t<isRRef_v<X>
|
||||
, remove_cv_t<remove_reference_t<X>> &&
|
||||
, remove_cv_t<remove_reference_t<X>> & >
|
||||
, remove_cv_t<X>>;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/meta/typelist.hpp"
|
||||
#include "lib/meta/typelist-util.hpp"
|
||||
#include "lib/meta/generator.hpp"
|
||||
|
|
|
|||
|
|
@ -136,9 +136,12 @@ namespace test{
|
|||
string
|
||||
showRefKind()
|
||||
{
|
||||
return std::is_lvalue_reference<R>::value? "REF"
|
||||
: std::is_rvalue_reference<R>::value? "MOV"
|
||||
: "VAL";
|
||||
using lib::meta::isLRef_v;
|
||||
using lib::meta::isRRef_v;
|
||||
|
||||
return isLRef_v<R>? "REF"
|
||||
: isRRef_v<R>? "MOV"
|
||||
: "VAL";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<map version="1.0.1">
|
||||
<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
|
||||
<node BACKGROUND_COLOR="#6666ff" CREATED="1434127882200" ID="ID_1452170048" MODIFIED="1734743418261" STYLE="fork" TEXT="Lumi">
|
||||
<node BACKGROUND_COLOR="#6666ff" CREATED="1434127882200" ID="ID_1452170048" MODIFIED="1764717453015" STYLE="fork" TEXT="Lumi">
|
||||
<font NAME="SansSerif" SIZE="25"/>
|
||||
<node CREATED="1434128046296" FOLDED="true" ID="ID_1900827283" MODIFIED="1679363052358" POSITION="right" TEXT="GUI">
|
||||
<font BOLD="true" NAME="SansSerif" SIZE="14"/>
|
||||
|
|
@ -51417,7 +51417,7 @@
|
|||
<node CREATED="1684890048701" ID="ID_1515151471" MODIFIED="1684890070142" TEXT="greift nested type bindings aus dem gegebenen value_type ab"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1718111942637" ID="ID_120263382" MODIFIED="1718112119523" TEXT="Thema: Iteartor-Result-Move">
|
||||
<node CREATED="1718111942637" ID="ID_120263382" MODIFIED="1774449616809" TEXT="Thema: Iteartor-Result-Move">
|
||||
<linktarget COLOR="#4627b7" DESTINATION="ID_120263382" ENDARROW="Default" ENDINCLINATION="-1618;155;" ID="Arrow_ID_1994292406" SOURCE="ID_526580433" STARTARROW="None" STARTINCLINATION="-646;-77;"/>
|
||||
<icon BUILTIN="yes"/>
|
||||
<node CREATED="1718112123510" ID="ID_705868253" MODIFIED="1718112157586" TEXT="das Konzept ist stark festgelegt auf Ergebnisse per Referenz">
|
||||
|
|
@ -51468,6 +51468,21 @@
|
|||
<node CREATED="1718112886431" ID="ID_996588888" MODIFIED="1718112899866" TEXT="noch als Terminal in IterEplorer"/>
|
||||
<node CREATED="1718112914131" ID="ID_38982413" MODIFIED="1718112923134" TEXT="und auch nicht in speziellen Containern"/>
|
||||
</node>
|
||||
<node COLOR="#3b316f" CREATED="1774450575923" ID="ID_625268615" MODIFIED="1774450575925" TEXT="(naja ... ein halbes Jahr später hab ich doch die Tür a bisserl aufgemacht)">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Beim zip-Iterator war eine einseitige Festlegung letztlich nicht sinnvoll; außerdem hatte ich, grade für den zip-Iterator sehr mühsam die ganze Pipeline aufgeräumt, so daß jetzt kein einziger unnötiger Dekorator mehr auftritt. Auf dieser Basis <i>kann man gestatten, </i>daß ein Iterator sein Ergebnis als value abliefert, und die nachgeschaltete Pipeline würde dann automatisch schwenken. Den gefährlichen operator-> unterdrücken wir in dem Fall per compile-time Assertion.
|
||||
</p>
|
||||
<p>
|
||||
Dennoch gilt »Ergebnis per Referenz« weiterhin als der Stanard-Fall
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<arrowlink COLOR="#726ea0" DESTINATION="ID_73007932" ENDARROW="Default" ENDINCLINATION="-605;-685;" ID="Arrow_ID_1417723074" STARTARROW="None" STARTINCLINATION="1034;49;"/>
|
||||
<font ITALIC="true" NAME="SansSerif" SIZE="10"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1684279342553" ID="ID_289621340" MODIFIED="1684279366302" TEXT="diverse Ausprägungen">
|
||||
|
|
@ -52360,6 +52375,7 @@
|
|||
</node>
|
||||
<node COLOR="#435e98" CREATED="1732499748626" ID="ID_73007932" MODIFIED="1732658339211" TEXT="nochmal untersuchen: können wir Value-Ergebnisse aus der Pipeline unterstützen?">
|
||||
<arrowlink COLOR="#4bb4e2" DESTINATION="ID_1558751662" ENDARROW="Default" ENDINCLINATION="411;23;" ID="Arrow_ID_1082389405" STARTARROW="None" STARTINCLINATION="-3;-253;"/>
|
||||
<linktarget COLOR="#726ea0" DESTINATION="ID_73007932" ENDARROW="Default" ENDINCLINATION="-605;-685;" ID="Arrow_ID_1417723074" SOURCE="ID_625268615" STARTARROW="None" STARTINCLINATION="1034;49;"/>
|
||||
<linktarget COLOR="#4e6fd7" DESTINATION="ID_73007932" ENDARROW="Default" ENDINCLINATION="-1571;53;" ID="Arrow_ID_1348614829" SOURCE="ID_1087558825" STARTARROW="None" STARTINCLINATION="-292;13;"/>
|
||||
<icon BUILTIN="help"/>
|
||||
<node COLOR="#435e98" CREATED="1732499767002" FOLDED="true" ID="ID_1245640841" MODIFIED="1732636236208" TEXT="Problem-1 : operator-> kann nicht unterstützt werden">
|
||||
|
|
@ -52394,7 +52410,7 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1732576781381" ID="ID_452524052" MODIFIED="1732576819125" TEXT="effektiv läd das das Problem bei konkreten Transformationen und Prädikaten ab">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1732576832125" ID="ID_443099186" MODIFIED="1732576877954" TEXT="...denn eine Funktion non-const-Referenzen nimmt, scheitert"/>
|
||||
<node CREATED="1732576832125" ID="ID_443099186" MODIFIED="1732576877954" TEXT="...denn eine Funktion die non-const-Referenzen nimmt, scheitert"/>
|
||||
<node CREATED="1732576887573" ID="ID_687212437" MODIFIED="1732576907676" TEXT="erscheint akzepabel, da das i.d.R Lambdas für den Einzelfall sind"/>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -52606,7 +52622,7 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1535891065189" FOLDED="true" ID="ID_1233342893" MODIFIED="1732655076691" TEXT="Iterator-Monade">
|
||||
<node COLOR="#338800" CREATED="1535891065189" FOLDED="true" ID="ID_1233342893" MODIFIED="1774486122123" TEXT="Iterator-Monade">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
|
|
@ -52848,7 +52864,7 @@
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1535891140563" ID="ID_1503014369" MODIFIED="1687456594305" TEXT="IterExplorer (pipeline)">
|
||||
<node COLOR="#435e98" CREATED="1535891140563" ID="ID_1503014369" MODIFIED="1774486122123" TEXT="IterExplorer (pipeline)">
|
||||
<icon BUILTIN="forward"/>
|
||||
<node CREATED="1535891145922" ID="ID_1982906906" MODIFIED="1535891149925" TEXT="zweiter Anlauf">
|
||||
<node CREATED="1535891150825" ID="ID_451523751" MODIFIED="1535891155914" TEXT="funktioniert">
|
||||
|
|
@ -53276,9 +53292,7 @@
|
|||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1774470901308" ID="ID_1506170632" MODIFIED="1774471215712" TEXT="was hier nun passiert...">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<ul>
|
||||
<li>
|
||||
|
|
@ -53301,9 +53315,7 @@
|
|||
<node CREATED="1774471570043" ID="ID_1241566646" MODIFIED="1774471605751" TEXT="Bauchgefühl ⟹ das strip-pointer in RangeIter ist eine »verschleppte Altlast«">
|
||||
<node CREATED="1774471625212" ID="ID_451783687" MODIFIED="1774471702711" TEXT="dafür spricht das Changeset e176e540043177">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
commit e176e540043177b57b9dfd00ac1b1c837d689a6c
|
||||
|
|
@ -53372,9 +53384,7 @@
|
|||
<node CREATED="1774471707012" ID="ID_222828708" MODIFIED="1774471731713" TEXT="(erst) vor zwei Jahren habe ich das Problem versucht bei der Wurzel zu packen"/>
|
||||
<node CREATED="1774471733381" ID="ID_8755833" MODIFIED="1774472109854" TEXT="aber exakt in diesem Changeset habe ich den remove-ptr von früher praktisch übernommen">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Obwohl diese Stelle, <i>rein logisch betrachtet,</i> 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 <i>einfachen Werten im Container</i>. 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“
|
||||
|
|
@ -53400,9 +53410,7 @@
|
|||
<node CREATED="1774472869933" ID="ID_1252763757" MODIFIED="1774472892212" TEXT="bricht massiv"/>
|
||||
<node CREATED="1774472893514" ID="ID_276836465" MODIFIED="1774472921127">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
ist auch logisch: T* ist <b>hier</b> ein »Iterator«
|
||||
|
|
@ -53412,9 +53420,7 @@
|
|||
<node CREATED="1774472936587" ID="ID_894773701" MODIFIED="1774473005367" TEXT="Bedeutet: T wäre der »value«"/>
|
||||
<node CREATED="1774472959721" ID="ID_179295366" MODIFIED="1774473016083">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<i>speziell hier</i> <u>müssen</u> wir den Pointer strippen
|
||||
|
|
@ -53427,9 +53433,7 @@
|
|||
</node>
|
||||
<node CREATED="1774473065347" ID="ID_644087481" MODIFIED="1774473505092" TEXT="also war es zwar ein pragmatischer Fix — aber ein Spezial-Eingriff ist hier notwendig">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
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...
|
||||
|
|
@ -53439,9 +53443,7 @@
|
|||
</node>
|
||||
<node CREATED="1774473105365" ID="ID_863796636" MODIFIED="1774473770697" TEXT="Grund: Mismatch zwischen STL-»Iteraor«-Begriff und unserem »Forward-Iterator«-Konzept">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
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 <b>der Container definiert die Typen</b>.
|
||||
|
|
@ -168599,6 +168601,159 @@ class Something
|
|||
<linktarget COLOR="#415ab4" DESTINATION="ID_197491932" ENDARROW="Default" ENDINCLINATION="-1574;159;" ID="Arrow_ID_1382804093" SOURCE="ID_1579820839" STARTARROW="None" STARTINCLINATION="-2029;0;"/>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1774627260591" FOLDED="true" ID="ID_1784884752" MODIFIED="1774628681299" TEXT="Grundzüge">
|
||||
<icon BUILTIN="back"/>
|
||||
<node CREATED="1774627283191" ID="ID_115112464" MODIFIED="1774628259773">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<b>Concept</b> ist eine spezielle Aufrufschnittstelle für eine bool constexpr
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Das heißt, der Rumpf eines Concepts ist eine bool constexpr und wird zur Compile-Zeit ausgewertet. Aber durch die Markierung als »Concept« kann es an besonderen Stellen in der Syntax verwendet werden
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
in der Deklaration von Template-Parametern
|
||||
</li>
|
||||
<li>
|
||||
als Constraint auf auto-Argumenten
|
||||
</li>
|
||||
<li>
|
||||
in der Result-Expression in einem <b>Requires-Ausdruck</b>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Darüberhinaus aber kann ein Concept auch als normale bool-constexpr direkt im Code ausgewertet werden. Ein Spezialfall davon ist die <b>Requires-Klausel</b>, mit der beliebige Contraints an eine Template-Definition oder Funktionsdefinition angefügt werden können
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1774627652885" ID="ID_250636866" MODIFIED="1774628267834">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
<b>Requires-Ausdruck</b> definiert Constraints
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
<node CREATED="1774627743029" ID="ID_1990543481" MODIFIED="1774627754085" TEXT="es erzeugt einen SFINAE-Scope"/>
|
||||
<node CREATED="1774627755233" ID="ID_1578349738" MODIFIED="1774627765109" TEXT="sein Ergebnis ist constexpr bool"/>
|
||||
<node CREATED="1774627767320" ID="ID_1887793857" MODIFIED="1774628409651" TEXT="er erzeugt declval-Parameter">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
Das ist der spezielle Knackpunkt, denn man kann dadurch weitere Parameter-Symbole einführen, die im Rump wie Objekte (im Sinn der C++ Spezifikation) verwendet werden können
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1774628423456" ID="ID_1786394343" MODIFIED="1774628641063" TEXT="der Rumpf ist eine Konjunktion von Ausdrücken"/>
|
||||
<node CREATED="1774627786507" ID="ID_1128631817" MODIFIED="1774627793600" TEXT="im Rumpf gibt es spezielle Syntax">
|
||||
<node CREATED="1774627797678" ID="ID_1288020421" MODIFIED="1774627872666" TEXT="typename X">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
der angeschriebene Typ muß valid sein. Das ist das klassische SFINAE
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1774627803598" ID="ID_18085442" MODIFIED="1774627908192" TEXT="expression">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
der angeschriebene Ausdruck muß übersetzbar und valide sein
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1774627813737" ID="ID_1661928474" MODIFIED="1774627962529" TEXT="{ expr } -> concept">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
der angeschriebene Ausdruck im Block muß übersetzbar und valide sein, <i>und sein Resultat-Wert</i> muß das Concept (als 1. Argument) erfüllen
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
<node CREATED="1774627839278" ID="ID_477641322" MODIFIED="1774627981787" TEXT="requires-Klausel">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
die Requires-Klausel darf nicht scheitern
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1774627985459" ID="ID_1134994952" MODIFIED="1774628159532" TEXT="requires-Klausel verwandelt Bool-Check in Compile-Fehler">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
...sie ist also eine spezielle Form einer static-assert, welche normalerweise geräuschlos scheitert; wenn eine requires-Klausel in normalem Code steht, wird sie geprüft und führt zum Compile-Fehler, wenn ihr Rumpf zu false evaluiert
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1774562489996" ID="ID_1581229318" MODIFIED="1774563657284" TEXT="Iteratoren">
|
||||
<linktarget COLOR="#4c86e5" DESTINATION="ID_1581229318" ENDARROW="Default" ENDINCLINATION="-2159;523;" ID="Arrow_ID_58259000" SOURCE="ID_389716197" STARTARROW="None" STARTINCLINATION="-1280;85;"/>
|
||||
<node CREATED="1774562670530" ID="ID_1893015368" LINK="https://en.cppreference.com/w/cpp/iterator.html" MODIFIED="1774562682659" TEXT="siehe: »Iterator-Library«">
|
||||
<icon BUILTIN="info"/>
|
||||
<node CREATED="1774562734572" ID="ID_1236048963" LINK="https://stackoverflow.com/q/79182541/444796" MODIFIED="1774562900395" TEXT="SO: Which concept to use for checking an iterator's value type?">
|
||||
<linktarget COLOR="#68bac0" DESTINATION="ID_1236048963" ENDARROW="Default" ENDINCLINATION="-140;81;" ID="Arrow_ID_1198778210" SOURCE="ID_44489370" STARTARROW="Default" STARTINCLINATION="73;-56;"/>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
</node>
|
||||
<node CREATED="1774562494210" ID="ID_406768197" MODIFIED="1774562510492" TEXT="es gibt concepts entsprechend den alten »Iterator-Tags«">
|
||||
<node CREATED="1774562519927" ID="ID_59067545" MODIFIED="1774562525706" TEXT="z.b. std::input_iterator"/>
|
||||
<node CREATED="1774562769903" ID="ID_70257471" MODIFIED="1774562798761" TEXT="std::indirectly_writable">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head/>
|
||||
<body>
|
||||
<p>
|
||||
daß ein Wert in das durch den Iterator referenzierte Objekt geschrieben werden kann
|
||||
</p>
|
||||
</body>
|
||||
</html></richcontent>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#e0ceaa" COLOR="#690f14" CREATED="1774562531981" ID="ID_1945817338" MODIFIED="1774562551787" TEXT="Vorsicht: damit werden std::iterator_traits<IT> tendentiell unzuverlässig">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1774562559193" ID="ID_480443164" MODIFIED="1774562582178" TEXT="weil man jetzt durch die Concepts direkt auf Vorhandensein der Operationen prüfen kann"/>
|
||||
<node CREATED="1774562583419" ID="ID_836415227" MODIFIED="1774562603383" TEXT="daher muß man sich nicht mehr auf ein Tag oder eine iterator_traits-Spezialisierung verlassen"/>
|
||||
<node CREATED="1774562605260" ID="ID_1469937348" MODIFIED="1774562624364" TEXT="⟹ was man nicht (mehr) braucht pflegt man nicht"/>
|
||||
</node>
|
||||
<node CREATED="1774562638656" ID="ID_44489370" MODIFIED="1774562906705" TEXT="für Typdefiniitionen gibt es jetzt neue Traits">
|
||||
<arrowlink COLOR="#68bac0" DESTINATION="ID_1236048963" ENDARROW="Default" ENDINCLINATION="-140;81;" ID="Arrow_ID_1198778210" STARTARROW="Default" STARTINCLINATION="73;-56;"/>
|
||||
<node CREATED="1774562885072" MODIFIED="1774562885072" TEXT="iter_value_t"/>
|
||||
<node CREATED="1774562885073" MODIFIED="1774562885073" TEXT="iter_reference_t"/>
|
||||
<node CREATED="1774562885073" MODIFIED="1774562885073" TEXT="iter_const_reference_t"/>
|
||||
<node CREATED="1774562885073" MODIFIED="1774562885073" TEXT="iter_difference_t"/>
|
||||
<node CREATED="1774562885073" MODIFIED="1774562885073" TEXT="iter_rvalue_reference_t"/>
|
||||
<node CREATED="1774562885073" MODIFIED="1774562885073" TEXT="iter_common_reference_t"/>
|
||||
</node>
|
||||
<node CREATED="1774563571546" ID="ID_23392065" MODIFIED="1774563583062" TEXT="Bedeutung der Typen">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1774563584945" ID="ID_1664104813" MODIFIED="1774563596058" TEXT="was mir der Iterator liefert ⟹ reference"/>
|
||||
<node CREATED="1774563596935" ID="ID_1541313986" MODIFIED="1774563614293" TEXT="in was ich diesen »Wert« speichern kann ⟹ value"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1698089401358" FOLDED="true" ID="ID_29991404" MODIFIED="1698090231201" TEXT="�� Wunsch: named Arguments">
|
||||
<linktarget COLOR="#967b86" DESTINATION="ID_29991404" ENDARROW="Default" ENDINCLINATION="-1293;117;" ID="Arrow_ID_152389560" SOURCE="ID_713507066" STARTARROW="None" STARTINCLINATION="-2574;139;"/>
|
||||
|
|
|
|||
Loading…
Reference in a new issue