Implementation (I) : IterStateWrapper as foundation (passing test)
This commit is contained in:
parent
ab2a6b2fce
commit
83a0f4b41f
2 changed files with 232 additions and 5 deletions
|
|
@ -256,6 +256,100 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Another Lumiera Forward Iterator building block, based on incorporating a state type
|
||||||
|
* right into the iterator. Contrast this to IterAdapter referring to an controlling
|
||||||
|
* container behind the scenes. Here, all of the state is assumed to live in the
|
||||||
|
* custom type embedded into this iterator, accessed and manipulated through
|
||||||
|
* an set of free function to be resolved by ADL.
|
||||||
|
*
|
||||||
|
* @see IterExplorer a monadic iterator built on top of IterStateWrapper
|
||||||
|
* @see iter-explorer-test.hpp
|
||||||
|
* @see iter-adaptor-test.cpp
|
||||||
|
*/
|
||||||
|
template<typename T, class ST =T>
|
||||||
|
class IterStateWrapper
|
||||||
|
: public lib::BoolCheckable<IterStateWrapper<T,ST> >
|
||||||
|
{
|
||||||
|
ST core_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef typename iter::TypeBinding<T>::pointer pointer;
|
||||||
|
typedef typename iter::TypeBinding<T>::reference reference;
|
||||||
|
typedef typename iter::TypeBinding<T>::value_type value_type;
|
||||||
|
|
||||||
|
IterStateWrapper (ST initialState)
|
||||||
|
: core_(initialState)
|
||||||
|
{
|
||||||
|
checkPos(core_);
|
||||||
|
}
|
||||||
|
|
||||||
|
IterStateWrapper ()
|
||||||
|
: core_()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
/* === lumiera forward iterator concept === */
|
||||||
|
|
||||||
|
reference
|
||||||
|
operator*() const
|
||||||
|
{
|
||||||
|
_maybe_throw();
|
||||||
|
return yield (core_); // extension point: yield
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer
|
||||||
|
operator->() const
|
||||||
|
{
|
||||||
|
_maybe_throw();
|
||||||
|
return & yield(core_); // extension point: yield
|
||||||
|
}
|
||||||
|
|
||||||
|
IterStateWrapper&
|
||||||
|
operator++()
|
||||||
|
{
|
||||||
|
_maybe_throw();
|
||||||
|
iterNext (core_); // extension point: iterNext
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
isValid () const
|
||||||
|
{
|
||||||
|
return checkPos(core_); // extension point: checkPos
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
empty () const
|
||||||
|
{
|
||||||
|
return !isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void
|
||||||
|
_maybe_throw() const
|
||||||
|
{
|
||||||
|
if (!isValid())
|
||||||
|
_throwIterExhausted();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// comparison of equivalent iterators
|
||||||
|
friend bool operator== (IterStateWrapper const& il, IterStateWrapper const& ir)
|
||||||
|
{
|
||||||
|
return (il.empty() && ir.empty())
|
||||||
|
|| (il.isValid() && ir.isValid() && *il == *ir);
|
||||||
|
}
|
||||||
|
friend bool operator!= (IterStateWrapper const& il, IterStateWrapper const& ir)
|
||||||
|
{
|
||||||
|
return ! (il == ir);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,18 +31,34 @@
|
||||||
#include "lib/linked-elements.hpp"
|
#include "lib/linked-elements.hpp"
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <iostream>
|
//#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
|
|
||||||
|
namespace iter {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct TypeBinding<uint>
|
||||||
|
{
|
||||||
|
typedef uint value_type;
|
||||||
|
typedef uint const& reference;
|
||||||
|
typedef uint const* pointer;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace test{
|
namespace test{
|
||||||
|
|
||||||
using ::Test;
|
using ::Test;
|
||||||
// using boost::lexical_cast;
|
// using boost::lexical_cast;
|
||||||
// using util::for_each;
|
// using util::for_each;
|
||||||
// using util::isnil;
|
// using util::isnil;
|
||||||
|
using util::isnil;
|
||||||
using util::isSameObject;
|
using util::isSameObject;
|
||||||
// using std::vector;
|
// using std::vector;
|
||||||
// using std::cout;
|
// using std::cout;
|
||||||
|
|
@ -53,12 +69,86 @@ namespace test{
|
||||||
|
|
||||||
namespace { // test dummy source iterator
|
namespace { // test dummy source iterator
|
||||||
|
|
||||||
uint NUM_ELMS = 10;
|
// uint NUM_ELMS = 10;
|
||||||
|
|
||||||
|
class State
|
||||||
|
{
|
||||||
|
uint p,e;
|
||||||
|
|
||||||
|
public:
|
||||||
|
State(uint start, uint end)
|
||||||
|
: p(start)
|
||||||
|
, e(end)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
friend bool
|
||||||
|
checkPos (State const& st)
|
||||||
|
{
|
||||||
|
return st.p < st.e;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend uint const&
|
||||||
|
yield (State const& st)
|
||||||
|
{
|
||||||
|
return checkPos(st)? st.p : st.e;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend void
|
||||||
|
iterNext (State & st)
|
||||||
|
{
|
||||||
|
if (!checkPos (st)) return;
|
||||||
|
++st.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
class NumberSequence
|
class NumberSequence
|
||||||
|
: public IterStateWrapper<uint, State>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit
|
||||||
|
NumberSequence(uint end = 0)
|
||||||
|
: IterStateWrapper<uint,State> (State(0,end))
|
||||||
|
{ }
|
||||||
|
NumberSequence(uint start, uint end)
|
||||||
|
: IterStateWrapper<uint,State> (State(start,end))
|
||||||
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline NumberSequence
|
||||||
|
seq (uint end)
|
||||||
|
{
|
||||||
|
return NumberSequence(end);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline NumberSequence
|
||||||
|
seq (uint start, uint end)
|
||||||
|
{
|
||||||
|
return NumberSequence(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
NumberSequence NIL_Sequence;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Diagnostic helper: "squeeze out" the given iterator
|
||||||
|
* and join all yielded elements into a string
|
||||||
|
*/
|
||||||
|
template<class II>
|
||||||
|
inline string
|
||||||
|
materialise (II & ii)
|
||||||
|
{
|
||||||
|
std::ostringstream buff;
|
||||||
|
while (ii)
|
||||||
|
{
|
||||||
|
buff << *ii;
|
||||||
|
if (++ii) buff << "-";
|
||||||
|
}
|
||||||
|
return buff.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // (END) impl test dummy container
|
} // (END) impl test dummy container
|
||||||
|
|
||||||
|
|
@ -104,10 +194,45 @@ namespace test{
|
||||||
{
|
{
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
run (Arg arg)
|
run (Arg)
|
||||||
{
|
{
|
||||||
verifyChainedIterators ();
|
verifyStateAdapter();
|
||||||
verifyComparisons ();
|
|
||||||
|
UNIMPLEMENTED ("IterExplorer Monad");
|
||||||
|
verifyChainedIterators();
|
||||||
|
verifyRawChainedIterators();
|
||||||
|
|
||||||
|
verifyDepthFirstExploration();
|
||||||
|
verifyBreadthFirstExploration();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** @test all of the following IterExplorer flavours are built on top
|
||||||
|
* of a special iterator adapter, centred at the notion of an iterable
|
||||||
|
* state element type. The actual iterator just embodies one element
|
||||||
|
* of this state representation, and typically there is not an hidden
|
||||||
|
* back-link to some kind of container in charge of the elements yielded
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
verifyStateAdapter ()
|
||||||
|
{
|
||||||
|
NumberSequence ii = seq(5);
|
||||||
|
CHECK (!isnil (ii));
|
||||||
|
CHECK (0 == *ii);
|
||||||
|
CHECK (materialise(ii) == "0-1-2-3-4");
|
||||||
|
CHECK ( isnil (ii));
|
||||||
|
CHECK (!ii);
|
||||||
|
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, *ii );
|
||||||
|
VERIFY_ERROR (ITER_EXHAUST, ++ii );
|
||||||
|
|
||||||
|
ii = seq(5,8);
|
||||||
|
CHECK (materialise(ii) == "5-6-7");
|
||||||
|
|
||||||
|
ii = NIL_Sequence;
|
||||||
|
CHECK ( isnil (ii));
|
||||||
|
CHECK (!ii);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -122,6 +247,7 @@ namespace test{
|
||||||
void
|
void
|
||||||
verifyChainedIterators ()
|
verifyChainedIterators ()
|
||||||
{
|
{
|
||||||
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
typedef ChainedIters<NumberSequence> Chain;
|
typedef ChainedIters<NumberSequence> Chain;
|
||||||
|
|
||||||
Chain ci = iter::chain (seq(5),seq(7),seq(9));
|
Chain ci = iter::chain (seq(5),seq(7),seq(9));
|
||||||
|
|
@ -159,6 +285,7 @@ namespace test{
|
||||||
CHECK (0 == *s9);
|
CHECK (0 == *s9);
|
||||||
pullOut (s9);
|
pullOut (s9);
|
||||||
CHECK (isnil(s9));
|
CHECK (isnil(s9));
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -169,6 +296,7 @@ namespace test{
|
||||||
void
|
void
|
||||||
verifyRawChainedIterators ()
|
verifyRawChainedIterators ()
|
||||||
{
|
{
|
||||||
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
typedef LinkedElements<NumberSequence, linked_elements::NoOwnership> IterContainer;
|
typedef LinkedElements<NumberSequence, linked_elements::NoOwnership> IterContainer;
|
||||||
typedef IterContainer::const_iterator IterIter;
|
typedef IterContainer::const_iterator IterIter;
|
||||||
|
|
||||||
|
|
@ -236,6 +364,7 @@ namespace test{
|
||||||
CHECK (isnil(s5));
|
CHECK (isnil(s5));
|
||||||
CHECK (isnil(s7));
|
CHECK (isnil(s7));
|
||||||
CHECK (isnil(s9));
|
CHECK (isnil(s9));
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -276,11 +405,13 @@ namespace test{
|
||||||
void
|
void
|
||||||
verifyDepthFirstExploration ()
|
verifyDepthFirstExploration ()
|
||||||
{
|
{
|
||||||
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
typedef DepthFirstExplorer<NumberSequence> DepthFirst;
|
typedef DepthFirstExplorer<NumberSequence> DepthFirst;
|
||||||
DepthFirst root (seq(1));
|
DepthFirst root (seq(1));
|
||||||
|
|
||||||
NumberSequence explorationResult = root >>= exploreChildren(8);
|
NumberSequence explorationResult = root >>= exploreChildren(8);
|
||||||
CHECK (materialise(explorationResult) == "1-1-1-1-2-2-3-4-2-3-5-6-4-7-8");
|
CHECK (materialise(explorationResult) == "1-1-1-1-2-2-3-4-2-3-5-6-4-7-8");
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -294,11 +425,13 @@ namespace test{
|
||||||
void
|
void
|
||||||
verifyBreadthFirstExploration ()
|
verifyBreadthFirstExploration ()
|
||||||
{
|
{
|
||||||
|
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
typedef BreadthFirstExplorer<NumberSequence> BreadthFirst;
|
typedef BreadthFirstExplorer<NumberSequence> BreadthFirst;
|
||||||
BreadthFirst root (seq(1));
|
BreadthFirst root (seq(1));
|
||||||
|
|
||||||
NumberSequence explorationResult = root >>= exploreChildren(8);
|
NumberSequence explorationResult = root >>= exploreChildren(8);
|
||||||
CHECK (materialise(explorationResult) == "1-1-2-1-2-3-4-1-2-3-4-5-6-7-8");
|
CHECK (materialise(explorationResult) == "1-1-2-1-2-3-4-1-2-3-4-5-6-7-8");
|
||||||
|
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #892
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue