implemented chained-iterators
...using the IterExplorer building blocks
This commit is contained in:
parent
d14b37a71d
commit
8db5413199
2 changed files with 157 additions and 26 deletions
|
|
@ -66,9 +66,13 @@
|
|||
//#include "lib/bool-checkable.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/iter-adapter.hpp"
|
||||
#include "lib/iter-stack.hpp"
|
||||
#include "lib/meta/trait.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <stack>
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
|
@ -239,7 +243,7 @@ namespace lib {
|
|||
return this->operator* ();
|
||||
}
|
||||
|
||||
IterExplorer&
|
||||
IterExplorer const&
|
||||
accessRemainingElements()
|
||||
{
|
||||
this->operator++ ();
|
||||
|
|
@ -253,6 +257,8 @@ namespace lib {
|
|||
namespace iter_explorer { ///< predefined policies and configurations
|
||||
|
||||
using util::unConst;
|
||||
using boost::enable_if;
|
||||
using boost::disable_if;
|
||||
|
||||
/**
|
||||
* Building block: evaluating source elements.
|
||||
|
|
@ -286,6 +292,7 @@ namespace lib {
|
|||
struct UnalteredPassThrough<IT(IT)>
|
||||
{
|
||||
IT operator() (IT elm) const { return elm; }
|
||||
bool operator! () const { return false; } ///< identity function is always valid
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -336,7 +343,7 @@ namespace lib {
|
|||
}
|
||||
|
||||
void
|
||||
setSourceSequence (SRC & followUpSourceElements)
|
||||
setSourceSequence (SRC const& followUpSourceElements)
|
||||
{
|
||||
REQUIRE (explorer_);
|
||||
srcSeq_ = followUpSourceElements;
|
||||
|
|
@ -407,26 +414,94 @@ namespace lib {
|
|||
}
|
||||
|
||||
void
|
||||
followUp (SRC & followUpSourceElements)
|
||||
followUp (SRC const& followUpSourceElements)
|
||||
{
|
||||
this->setSourceSequence (followUpSourceElements);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Special configuration for combining / flattening the results
|
||||
* of a sequence of iterators
|
||||
*/
|
||||
template<class SEQ>
|
||||
class ChainedIters
|
||||
|
||||
template<class IT>
|
||||
struct _is_iterator_of_iterators
|
||||
{
|
||||
/////////////TODO unimplemented
|
||||
typedef typename IT::value_type IteratorElementType;
|
||||
|
||||
enum{ value = meta::can_IterForEach<IteratorElementType>::value };
|
||||
};
|
||||
|
||||
|
||||
template<class ITI, class SEQ>
|
||||
class ChainedIteratorImpl
|
||||
: public CombinedIteratorEvaluation<ITI, SEQ(SEQ)
|
||||
, UnalteredPassThrough
|
||||
>
|
||||
{ };
|
||||
|
||||
|
||||
/**
|
||||
* Special iterator configuration for combining / flattening the
|
||||
* results of a sequence of iterators. This sequence of source iterators
|
||||
* is assumed to be available as "Iterator yielding Iterators".
|
||||
* The resulting class is a Lumiera Forward Iterator, delivering all the
|
||||
* elements of all source iterators in sequence.
|
||||
* @remarks this is quite similar to the IterExplorer monad, but without
|
||||
* binding an exploration function to produce the result sequences.
|
||||
* Rather, the result sequences are directly pulled from the source
|
||||
* sequence, which thus needs to be an "Iterator of Iterators".
|
||||
* Beyond that, the implementation relies on the same building
|
||||
* blocks as used for the full-blown IterExplorer.
|
||||
* @param ITI iterator of iterators
|
||||
* @param SEQ type of the individual sequence (iterator).
|
||||
* The value_type of this sequence will be the overall
|
||||
* resulting value type of the flattened sequence
|
||||
*/
|
||||
template<class ITI, class SEL = void>
|
||||
class ChainedIters;
|
||||
|
||||
template<class ITI>
|
||||
class ChainedIters<ITI, typename enable_if< _is_iterator_of_iterators<ITI> >::type
|
||||
>
|
||||
: public IterStateWrapper<typename ITI::value_type::value_type
|
||||
,ChainedIteratorImpl<ITI, typename ITI::value_type>
|
||||
>
|
||||
{
|
||||
public:
|
||||
ChainedIters(ITI const& iteratorOfIterators)
|
||||
{ // note: default ctor on parent -> empty sequences
|
||||
this->stateCore().setSourceSequence (iteratorOfIterators);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience specialisation: manage the sequence of iterators automatically.
|
||||
* @note in this case the \em first template parameter denotes the \em element sequence type;
|
||||
* we use a IterStack to hold the sequence-of-iterators in heap storage.
|
||||
* @warning this specialisation will not be picked, if the \em value-type
|
||||
* of the given iterator is itself an iterator
|
||||
*/
|
||||
template<class SEQ>
|
||||
class ChainedIters<SEQ, typename disable_if< _is_iterator_of_iterators<SEQ> >::type
|
||||
>
|
||||
: public IterStateWrapper<typename SEQ::value_type
|
||||
,ChainedIteratorImpl<IterStack<SEQ>, SEQ>
|
||||
>
|
||||
{
|
||||
public:
|
||||
typedef IterStack<SEQ> IteratorIterator;
|
||||
|
||||
ChainedIters(IteratorIterator const& iteratorOfIterators)
|
||||
{
|
||||
this->stateCore().setSourceSequence (iteratorOfIterators);
|
||||
}
|
||||
|
||||
/** empty result sequence by default */
|
||||
ChainedIters() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper template to bootstrap a chain of IterExplorers.
|
||||
* This is a "state corer", which basically just wraps a given
|
||||
* This is a "state core", which basically just wraps a given
|
||||
* source iterator and provides the necessary free functions
|
||||
* (iteration control API) to use this as iteration state
|
||||
* within IterExplorer.
|
||||
|
|
@ -474,16 +549,74 @@ namespace lib {
|
|||
|
||||
|
||||
template<class IT>
|
||||
IterExplorer<iter_explorer::WrappedSequence<IT> >
|
||||
inline IterExplorer<iter_explorer::WrappedSequence<IT> >
|
||||
exploreIter (IT const& srcSeq)
|
||||
{
|
||||
return IterExplorer<iter_explorer::WrappedSequence<IT> > (srcSeq);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
iterChain(IT const& seq)
|
||||
{
|
||||
typename iter_explorer::ChainedIters<IT>::IteratorIterator sequenceOfIterators;
|
||||
|
||||
sequenceOfIterators.push (seq);
|
||||
return iter_explorer::ChainedIters<IT>(sequenceOfIterators);
|
||||
}
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
iterChain(IT const& seq1, IT const& seq2)
|
||||
{
|
||||
typename iter_explorer::ChainedIters<IT>::IteratorIterator sequenceOfIterators;
|
||||
|
||||
sequenceOfIterators.push (seq2);
|
||||
sequenceOfIterators.push (seq1);
|
||||
return iter_explorer::ChainedIters<IT>(sequenceOfIterators);
|
||||
}
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
iterChain(IT const& seq1, IT const& seq2, IT const& seq3)
|
||||
{
|
||||
typename iter_explorer::ChainedIters<IT>::IteratorIterator sequenceOfIterators;
|
||||
|
||||
sequenceOfIterators.push (seq3);
|
||||
sequenceOfIterators.push (seq2);
|
||||
sequenceOfIterators.push (seq1);
|
||||
return iter_explorer::ChainedIters<IT>(sequenceOfIterators);
|
||||
}
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
iterChain(IT const& seq1, IT const& seq2, IT const& seq3, IT const& seq4)
|
||||
{
|
||||
typename iter_explorer::ChainedIters<IT>::IteratorIterator sequenceOfIterators;
|
||||
|
||||
sequenceOfIterators.push (seq4);
|
||||
sequenceOfIterators.push (seq3);
|
||||
sequenceOfIterators.push (seq2);
|
||||
sequenceOfIterators.push (seq1);
|
||||
return iter_explorer::ChainedIters<IT>(sequenceOfIterators);
|
||||
}
|
||||
|
||||
template<class IT>
|
||||
inline iter_explorer::ChainedIters<IT>
|
||||
iterChain(IT const& seq1, IT const& seq2, IT const& seq3, IT const& seq4, IT const& seq5)
|
||||
{
|
||||
typename iter_explorer::ChainedIters<IT>::IteratorIterator sequenceOfIterators;
|
||||
|
||||
sequenceOfIterators.push (seq5);
|
||||
sequenceOfIterators.push (seq4);
|
||||
sequenceOfIterators.push (seq3);
|
||||
sequenceOfIterators.push (seq2);
|
||||
sequenceOfIterators.push (seq1);
|
||||
return iter_explorer::ChainedIters<IT>(sequenceOfIterators);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ namespace test{
|
|||
using std::endl;
|
||||
using std::string;
|
||||
using lib::LinkedElements;
|
||||
using lib::iter_explorer::ChainedIters;
|
||||
using lumiera::error::LUMIERA_ERROR_ITER_EXHAUST;
|
||||
|
||||
|
||||
|
|
@ -206,7 +207,6 @@ namespace test{
|
|||
verifyStateAdapter();
|
||||
|
||||
verifyMonadOperator ();
|
||||
UNIMPLEMENTED ("IterExplorer Monad");
|
||||
verifyChainedIterators();
|
||||
verifyRawChainedIterators();
|
||||
|
||||
|
|
@ -249,20 +249,19 @@ namespace test{
|
|||
|
||||
|
||||
|
||||
/** @test a simple and practical helper built on top of IterExplorer.
|
||||
/** @test a convenient helper built using IterExplorer building blocks.
|
||||
* The resulting iterator \em combines and \em flattens a sequence
|
||||
* of source iterators, resulting in a simple sequence accessible
|
||||
* again as iterator. Here we verify the convenience / default
|
||||
* implementation; it uses a STL container behind the scenes
|
||||
* to keep track of all the added source iterators
|
||||
* as iterator again. Here we verify the convenience / default
|
||||
* implementation; it uses a STL container (actually std:deque)
|
||||
* behind the scenes to keep track of all added source iterators.
|
||||
*/
|
||||
void
|
||||
verifyChainedIterators ()
|
||||
{
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||
typedef ChainedIters<NumberSequence> Chain;
|
||||
|
||||
Chain ci = iter::chain (seq(5),seq(7),seq(9));
|
||||
Chain ci = iterChain (seq(5),seq(7),seq(9));
|
||||
|
||||
CHECK (!isnil (ci));
|
||||
pullOut (ci);
|
||||
|
|
@ -271,11 +270,11 @@ namespace test{
|
|||
VERIFY_ERROR (ITER_EXHAUST, ++ci );
|
||||
|
||||
CHECK (isnil(Chain()));
|
||||
CHECK (iter::chain (NIL_Sequence));
|
||||
CHECK (!iterChain (NIL_Sequence));
|
||||
|
||||
// Iterator chaining "flattens" one level of indirection
|
||||
// Iterator chaining "flattens" one level of packaging
|
||||
NumberSequence s9 = seq(9);
|
||||
ci = iter::chain (s9);
|
||||
ci = iterChain (s9);
|
||||
|
||||
for ( ; s9 && ci; ++s9, ++ci )
|
||||
CHECK (*s9 == *ci);
|
||||
|
|
@ -288,7 +287,7 @@ namespace test{
|
|||
// per-instance state (like e.g. NumberSequence used for this test),
|
||||
// then the created chain is independent from the source iterators.
|
||||
s9 = seq(9);
|
||||
ci = iter::chain (s9);
|
||||
ci = iterChain (s9);
|
||||
CHECK (0 == *s9);
|
||||
CHECK (0 == *ci);
|
||||
|
||||
|
|
@ -297,7 +296,6 @@ namespace test{
|
|||
CHECK (0 == *s9);
|
||||
pullOut (s9);
|
||||
CHECK (isnil(s9));
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue