IterAdapter now passes test, but is still rather uggly...

This commit is contained in:
Fischlurch 2009-07-14 06:29:04 +02:00
parent e2cd4aba8a
commit b2f72ef0fc
2 changed files with 90 additions and 42 deletions

View file

@ -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

View file

@ -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()));
}
};