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
This commit is contained in:
Fischlurch 2017-10-29 14:51:51 +01:00
parent 7e241d9a11
commit 0682e449a3
3 changed files with 170 additions and 2 deletions

View file

@ -575,6 +575,102 @@ namespace lib {
/**
* Implementation of a _singleton value_ holder,
* which discards the contained value once "iterated"
*/
template<typename VAL>
class SingleValCore
{
typedef wrapper::ItemWrapper<VAL> Item;
Item theValue_;
public:
SingleValCore() { } ///< passive and empty
SingleValCore (VAL&& something)
: theValue_{forward<VAL> (something)}
{ }
Item const&
pipe () const
{
return theValue_;
}
void
advance ()
{
theValue_.reset();
}
bool
evaluate () const
{
return theValue_.isValid();
}
typedef typename std::remove_reference<VAL>::type * pointer;
typedef typename std::remove_reference<VAL>::type & reference;
typedef typename std::remove_reference<VAL>::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 VAL>
class SingleValIter
: public IterTool<SingleValCore<VAL>>
{
using _ValHolder = SingleValCore<VAL>;
using _IteratorImpl = IterTool<_ValHolder> ;
public:
SingleValIter ()
: _IteratorImpl{_ValHolder{}}
{ }
SingleValIter (VAL&& something)
: _IteratorImpl{_ValHolder{forward<VAL>(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<class VAL>
inline auto
singleValIterator (VAL&& something)
{
return SingleValIter<VAL>{forward<VAL>(something)};
}
template<class VAL>
inline auto
singleValIterator (VAL const& ref)
{
return SingleValIter<VAL>{ref};
}
/**
* Implementation of custom processing logic.

View file

@ -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<int>{};
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; }

View file

@ -4659,7 +4659,6 @@
<icon BUILTIN="ksmiletris"/>
<node CREATED="1509143431491" ID="ID_1535839304" MODIFIED="1509143436685" TEXT="Pfad normal weiterverarbeiten"/>
<node CREATED="1509143437202" ID="ID_1489524396" MODIFIED="1509143442917" TEXT="aber Abstieg im Baum manipulieren"/>
</node>
<node CREATED="1509143453151" ID="ID_373632759" MODIFIED="1509143457604" TEXT="speziell...">
<node CREATED="1509143459519" ID="ID_1727095948" MODIFIED="1509143468809" TEXT="existenz-Check l&#xe4;uft anders">
<node CREATED="1509143492194" ID="ID_835507213" MODIFIED="1509143513852" TEXT="getType und stringvergleich"/>
@ -4680,9 +4679,38 @@
da&#223; ich mich wieder mal &quot;akademisch&quot; verspielt habe.... :-P
</p>
</body>
</html></richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
</node>
<node CREATED="1509151268071" ID="ID_38582779" MODIFIED="1509151422017" TEXT="getChildren aufbohren">
<icon BUILTIN="pencil"/>
<node CREATED="1509151285749" ID="ID_1826645914" MODIFIED="1509151289049" TEXT="eigentlich einfach"/>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1509151289637" ID="ID_892381116" MODIFIED="1509151414927" TEXT="brauche singletonIter">
<icon BUILTIN="pencil"/>
<node CREATED="1509151296292" ID="ID_1050274308" MODIFIED="1509151411655" TEXT="liefert ein einziges Element"/>
<node CREATED="1509151305602" ID="ID_452317335" MODIFIED="1509151411655" TEXT="als IterSource verpackt"/>
<node CREATED="1509151309866" ID="ID_1109789284" MODIFIED="1509151411655" TEXT="sollte es als als Basis iter implementieren">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
...und die IterSource dann nur &#252;ber WrapIter definieren.
</p>
<p>
Schichten-Prinzip...
</p>
</body>
</html>
</richcontent>
<icon BUILTIN="ksmiletris"/>
</node>
<node CREATED="1509151381113" ID="ID_779657015" MODIFIED="1509151411655" TEXT="brauche ItemWrapper f&#xfc;r beliebiges Element"/>
<node CREATED="1509151390495" ID="ID_947844248" MODIFIED="1509151411655" TEXT="Idee: TransformIter aufbohren">
<icon BUILTIN="help"/>
</node>
</node>
</node>
</node>
</node>