IterAdapter now passes test, but is still rather uggly...
This commit is contained in:
parent
e2cd4aba8a
commit
b2f72ef0fc
2 changed files with 90 additions and 42 deletions
|
|
@ -42,20 +42,15 @@
|
|||
#define LIB_ITER_ADAPTOR_H
|
||||
|
||||
|
||||
//#include "include/logging.h"
|
||||
#include "lib/error.hpp"
|
||||
#include "lib/bool-checkable.hpp"
|
||||
//#include "lib/util.hpp"
|
||||
|
||||
//#include <vector>
|
||||
//#include <boost/noncopyable.hpp>
|
||||
#include <boost/type_traits/remove_pointer.hpp>
|
||||
|
||||
|
||||
|
||||
namespace lib {
|
||||
|
||||
// using util::for_each;
|
||||
using boost::remove_pointer;
|
||||
|
||||
|
||||
|
|
@ -80,20 +75,19 @@ namespace lib {
|
|||
: public lib::BoolCheckable<IterAdapter<POS,CON> >
|
||||
{
|
||||
const CON* source_;
|
||||
POS pos_;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////TODO: implement empty test
|
||||
/////////////////////////////////////////////////////////////////////////TODO: implement comparisons
|
||||
mutable POS pos_;
|
||||
|
||||
public:
|
||||
typedef typename POS::pointer pointer; //////////////////TODO: do we really need all those typedefs???
|
||||
typedef typename POS::pointer pointer;
|
||||
typedef typename POS::reference reference;
|
||||
typedef typename POS::value_type value_type;
|
||||
|
||||
IterAdapter (const CON* src, const POS& startpos)
|
||||
: source_(src)
|
||||
, pos_(startpos)
|
||||
{ }
|
||||
{
|
||||
CON::iterValid(source_,pos_);
|
||||
}
|
||||
|
||||
IterAdapter ()
|
||||
: source_(0)
|
||||
|
|
@ -109,14 +103,14 @@ namespace lib {
|
|||
_maybe_throw();
|
||||
return *pos_;
|
||||
}
|
||||
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
_maybe_throw();
|
||||
return pos_;
|
||||
}
|
||||
|
||||
|
||||
IterAdapter&
|
||||
operator++()
|
||||
{
|
||||
|
|
@ -124,7 +118,7 @@ namespace lib {
|
|||
CON::iterNext (source_,pos_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
IterAdapter
|
||||
operator++(int)
|
||||
{
|
||||
|
|
@ -140,24 +134,43 @@ namespace lib {
|
|||
return (source_ && CON::iterValid(source_,pos_));
|
||||
}
|
||||
|
||||
bool
|
||||
empty () const
|
||||
{
|
||||
return !isValid();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
_maybe_throw() const
|
||||
{
|
||||
if (!isValid())
|
||||
throw lumiera::error::Invalid ("Can't iterate further",
|
||||
throw lumiera::error::Invalid ("Can't iterate further",
|
||||
lumiera::error::LUMIERA_ERROR_ITER_EXHAUST);
|
||||
}
|
||||
|
||||
/// comparison is allowed to access impl iterator
|
||||
template<class P1, class P2, class CX>
|
||||
friend bool operator== (IterAdapter<P1,CX> const&, IterAdapter<P2,CX> const&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
template<class P1, class P2, class CON>
|
||||
bool operator== (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return il.pos_ == ir.pos_; }
|
||||
|
||||
template<class P1, class P2, class CON>
|
||||
bool operator!= (IterAdapter<P1,CON> const& il, IterAdapter<P2,CON> const& ir) { return !(il == ir); }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** wrapper for an existing Iterator type,
|
||||
* automatically dereferencing the former's output.
|
||||
* automatically dereferencing the output of the former.
|
||||
* For this to work, the "source" iterator is expected
|
||||
* to be declared on \em pointers rather than on values.
|
||||
* @note bool checkable if and only if source is...
|
||||
|
|
@ -170,7 +183,8 @@ namespace lib {
|
|||
|
||||
public:
|
||||
typedef typename IT::value_type pointer;
|
||||
typedef typename remove_pointer<pointer>::type & reference;
|
||||
typedef typename remove_pointer<pointer>::type value_type;
|
||||
typedef value_type& reference;
|
||||
|
||||
|
||||
PtrDerefIter (IT srcIter)
|
||||
|
|
@ -185,20 +199,20 @@ namespace lib {
|
|||
{
|
||||
return *(*i_);
|
||||
}
|
||||
|
||||
|
||||
pointer
|
||||
operator->() const
|
||||
{
|
||||
return *i_;
|
||||
}
|
||||
|
||||
|
||||
PtrDerefIter&
|
||||
operator++()
|
||||
{
|
||||
++i_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
PtrDerefIter
|
||||
operator++(int)
|
||||
{
|
||||
|
|
@ -211,9 +225,25 @@ namespace lib {
|
|||
return bool(i_);
|
||||
}
|
||||
|
||||
bool
|
||||
empty () const
|
||||
{
|
||||
return !isValid();
|
||||
}
|
||||
|
||||
|
||||
/// comparison operator is allowed to access the underlying impl iterator
|
||||
template<class I1, class I2>
|
||||
friend bool operator== (PtrDerefIter<I1> const&, PtrDerefIter<I2> const&);
|
||||
};
|
||||
|
||||
|
||||
/// Supporting equality comparisons...
|
||||
template<class I1, class I2>
|
||||
bool operator== (PtrDerefIter<I1> const& il, PtrDerefIter<I2> const& ir) { return il.i_ == ir.i_; }
|
||||
|
||||
template<class I1, class I2>
|
||||
bool operator!= (PtrDerefIter<I1> const& il, PtrDerefIter<I2> const& ir) { return !(il == ir); }
|
||||
|
||||
|
||||
} // namespace lib
|
||||
|
|
|
|||
|
|
@ -25,12 +25,11 @@
|
|||
#include "lib/test/run.hpp"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
//#include "lib/scoped-ptrvect.hpp"
|
||||
#include "lib/iter-adapter.hpp"
|
||||
//#include "testdummy.hpp"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
|
||||
|
|
@ -38,9 +37,9 @@ namespace lib {
|
|||
namespace test{
|
||||
|
||||
using ::Test;
|
||||
// using util::isnil;
|
||||
using boost::lexical_cast;
|
||||
using util::for_each;
|
||||
using util::isnil;
|
||||
using std::vector;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
|
@ -75,38 +74,57 @@ namespace test{
|
|||
|
||||
typedef IterAdapter<_Vec::iterator, TestContainer> iterator;
|
||||
typedef IterAdapter<_Vec::const_iterator, TestContainer> const_iterator;
|
||||
typedef PtrDerefIter<iterator > ref_iterator;
|
||||
typedef PtrDerefIter<const_iterator> const_ref_iter;
|
||||
typedef PtrDerefIter<iterator > ref_iterator;
|
||||
typedef PtrDerefIter<const_iterator> const_ref_iter;
|
||||
|
||||
|
||||
iterator begin () { return iterator (this, numberz_.begin()); }
|
||||
iterator begin () { return iterator (this, numberz_.begin()); }
|
||||
const_iterator begin () const { return const_iterator (this, numberz_.begin()); }
|
||||
ref_iterator begin_ref () { return ref_iterator (begin()); }
|
||||
ref_iterator begin_ref () { return ref_iterator (begin()); }
|
||||
const_ref_iter begin_ref () const { return const_ref_iter (begin()); }
|
||||
|
||||
iterator end () { return iterator(); }
|
||||
iterator end () { return iterator(); }
|
||||
const_iterator end () const { return const_iterator(); }
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
protected: /* ==== API for the IterAdapter ==== */
|
||||
|
||||
friend class IterAdapter<_Vec::iterator, TestContainer>;
|
||||
friend class IterAdapter<_Vec::const_iterator,TestContainer>;
|
||||
|
||||
|
||||
/** Implementation of Iteration-logic: pull next element.
|
||||
* Implicitly this includes a test for iteration end.
|
||||
*/
|
||||
template<class ITER>
|
||||
static void
|
||||
iterNext (const TestContainer* src, ITER& pos)
|
||||
{
|
||||
if (iterValid(src,pos))
|
||||
++pos;
|
||||
iterValid(src,pos);
|
||||
}
|
||||
|
||||
/** Implementation of Iteration-logic: detect iteration end.
|
||||
* @note the problem here is that this implementation chooses
|
||||
* to use two representations of "bottom" (end, invalid).
|
||||
* The reason is, we want the default-constructed IterAdapter
|
||||
* also be the "bottom" value. Thus, when we detect the
|
||||
* iteration end by internal logic (\c numberz_.end() ), we
|
||||
* immediately transform this into the official "bottom"
|
||||
*/
|
||||
template<class ITER>
|
||||
static bool
|
||||
iterValid (const TestContainer* src, ITER& pos)
|
||||
{
|
||||
REQUIRE (src);
|
||||
return pos != src->numberz_.end();
|
||||
if ((pos != ITER(0)) && (pos != src->numberz_.end()))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
pos = ITER(0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -125,7 +143,7 @@ namespace test{
|
|||
virtual void
|
||||
run (Arg arg)
|
||||
{
|
||||
if (0 < arg.size()) NUM_ELMS = lexical_cast<uint> (arg[0]);
|
||||
if (0 < arg.size()) NUM_ELMS = lexical_cast<uint> (arg[0]);
|
||||
|
||||
TestContainer testElms (NUM_ELMS);
|
||||
simpleUsage (testElms);
|
||||
|
|
@ -167,13 +185,13 @@ namespace test{
|
|||
)
|
||||
{
|
||||
ASSERT (iter);
|
||||
// ASSERT (iter != elms.end()); ////////////////////////////TODO: implement comparison
|
||||
ASSERT (iter != elms.end());
|
||||
ASSERT (**iter == i-1);
|
||||
|
||||
// note: the previous run indeed modified
|
||||
// the element within the container.
|
||||
|
||||
// --(**iter); // doesn't compile, because it's const
|
||||
// --(**iter); // doesn't compile, because it's const ///////////////////////////////////TODO: duh! it *does* compile. why?
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
|
@ -206,12 +224,12 @@ namespace test{
|
|||
ASSERT (TestContainer::iterator() == elms.end());
|
||||
ASSERT (!(TestContainer::iterator()));
|
||||
ASSERT (!(elms.end()));
|
||||
// ASSERT (isnil (elms.end())); ////////////////////////////TODO: implement empty test
|
||||
ASSERT (isnil (elms.end()));
|
||||
|
||||
ASSERT (elms.begin());
|
||||
// ASSERT (!isnil (elms.begin())); ////////////////////////////TODO: implement empty test
|
||||
ASSERT (!isnil (elms.begin()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue