From 0682e449a3e9aa2d8ade9850b97b07d7b45e6055 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 29 Oct 2017 14:51:51 +0100 Subject: [PATCH] Library: a pseudo-iterator to yield just a single value ...which can be helpful when a function usually returns a somewhat dressed-up iterator, but needs to return a specific fixed value under some circumstances --- src/lib/itertools.hpp | 96 ++++++++++++++++++++++++++++++++ tests/library/itertools-test.cpp | 44 +++++++++++++++ wiki/thinkPad.ichthyo.mm | 32 ++++++++++- 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/src/lib/itertools.hpp b/src/lib/itertools.hpp index eb11a3feb..86a2e6705 100644 --- a/src/lib/itertools.hpp +++ b/src/lib/itertools.hpp @@ -575,6 +575,102 @@ namespace lib { + /** + * Implementation of a _singleton value_ holder, + * which discards the contained value once "iterated" + */ + template + class SingleValCore + { + typedef wrapper::ItemWrapper Item; + + Item theValue_; + + public: + SingleValCore() { } ///< passive and empty + + SingleValCore (VAL&& something) + : theValue_{forward (something)} + { } + + Item const& + pipe () const + { + return theValue_; + } + + void + advance () + { + theValue_.reset(); + } + + bool + evaluate () const + { + return theValue_.isValid(); + } + + typedef typename std::remove_reference::type * pointer; + typedef typename std::remove_reference::type & reference; + typedef typename std::remove_reference::type value_type; + }; + + + /** + * Pseudo-Iterator to yield just a single value. + * When incremented, the value is destroyed and + * the Iterator transitions to _exhausted state_. + * @remark as such might look nonsensical, but proves + * useful when a function yields an iterator, while + * producing an explicit value in some special case. + * @tparam VAL anything, value or reference to store + */ + template + class SingleValIter + : public IterTool> + { + using _ValHolder = SingleValCore; + using _IteratorImpl = IterTool<_ValHolder> ; + + public: + SingleValIter () + : _IteratorImpl{_ValHolder{}} + { } + + SingleValIter (VAL&& something) + : _IteratorImpl{_ValHolder{forward(something)}} + { } + + ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (SingleValIter) + }; + + + + /** Build a SingleValIter: convenience free function shortcut, + * to pick up just any value and wrap it as Lumiera Forward Iterator. + * @return Iterator to yield the value once + * @warning be sure to understand that we literally pick up and wrap anything + * provided as argument. If you pass a reference, we wrap a reference. + * If you want to wrap a copy, you have to do the copy yourself inline + */ + template + inline auto + singleValIterator (VAL&& something) + { + return SingleValIter{forward(something)}; + } + + template + inline auto + singleValIterator (VAL const& ref) + { + return SingleValIter{ref}; + } + + + + /** * Implementation of custom processing logic. diff --git a/tests/library/itertools-test.cpp b/tests/library/itertools-test.cpp index ca7fddc1e..c3025c496 100644 --- a/tests/library/itertools-test.cpp +++ b/tests/library/itertools-test.cpp @@ -115,6 +115,8 @@ namespace test{ verify_filterExtension(); verify_filterRepetitions(); + buildWrappedSingleElement(); + buildTransformingIterator (source.begin()); verifyPullLast(source.begin()); @@ -269,6 +271,48 @@ namespace test{ + /** @test wrap an arbitrary single element as pseudo-iterator */ + void + buildWrappedSingleElement() + { + uint i{12}; + + auto i1 = singleValIterator(12); + auto i2 = singleValIterator( i); + auto i3 = singleValIterator(&i); + + CHECK (not isnil(i1)); + CHECK (not isnil(i2)); + CHECK (not isnil(i3)); + CHECK (12 == *i1); + CHECK (12 == *i2); + CHECK (12 == **i3); + + i = 23; + CHECK (12 == *i1); + CHECK (23 == *i2); + CHECK (23 == **i3); + + ++i1; + ++i2; + ++i3; + CHECK (isnil(i1)); + CHECK (isnil(i2)); + CHECK (isnil(i3)); + VERIFY_ERROR (ITER_EXHAUST, *i1 ); + VERIFY_ERROR (ITER_EXHAUST, *i2 ); + VERIFY_ERROR (ITER_EXHAUST, *i3 ); + + // assignable as any iterator.. + i1 = singleValIterator(13); + CHECK (13 == *i1); + + i1 = SingleValIter{}; + CHECK (isnil(i1)); + } + + + static ulong addTwo (int i) { return i+2; } static int negate (int i) { return -i; } static int idFunc (int i) { return i; } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index f1db8a75f..a74c46729 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -4659,7 +4659,6 @@ - @@ -4680,9 +4679,38 @@ daß ich mich wieder mal "akademisch" verspielt habe.... :-P

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

+ ...und die IterSource dann nur über WrapIter definieren. +

+

+ Schichten-Prinzip... +

+
- +
+ + + + +