Victory! bashed the iter-adapters and the ScopedPtrVect into submission, finally.

This commit is contained in:
Fischlurch 2009-07-17 20:22:48 +02:00
parent 165cfc7fcd
commit 3f8d82a13f
3 changed files with 146 additions and 63 deletions

View file

@ -77,11 +77,44 @@
#include "lib/error.hpp"
#include "lib/bool-checkable.hpp"
#include <boost/type_traits/remove_const.hpp>
namespace lib {
namespace {
/**
* Helper for creating nested typedefs
* within the iterator adaptor, similar to what the STL does.
*/
template<typename TY>
struct IterTraits
{
typedef typename TY::pointer pointer;
typedef typename TY::reference reference;
typedef typename TY::value_type value_type;
};
template<typename TY>
struct IterTraits<TY *>
{
typedef TY value_type;
typedef TY& reference;
typedef TY* pointer;
};
template<typename TY>
struct IterTraits<const TY *>
{
typedef TY value_type;
typedef const TY& reference;
typedef const TY* pointer;
};
}
/**
* Adapter for building an implementation of the lumiera forward iterator concept.
@ -107,9 +140,9 @@ namespace lib {
mutable POS pos_;
public:
typedef typename POS::pointer pointer;
typedef typename POS::reference reference;
typedef typename POS::value_type value_type;
typedef typename IterTraits<POS>::pointer pointer;
typedef typename IterTraits<POS>::reference reference;
typedef typename IterTraits<POS>::value_type value_type;
IterAdapter (const CON* src, const POS& startpos)
: source_(src)
@ -243,9 +276,9 @@ namespace lib {
IT e_;
public:
typedef typename IT::pointer pointer;
typedef typename IT::reference reference;
typedef typename IT::value_type value_type;
typedef typename IterTraits<IT>::pointer pointer;
typedef typename IterTraits<IT>::reference reference;
typedef typename IterTraits<IT>::value_type value_type;
RangeIter (IT const& start, IT const& end)
: p_(start)
@ -287,6 +320,7 @@ namespace lib {
RangeIter&
operator++()
{
_maybe_throw();
++p_;
return *this;
}
@ -294,6 +328,7 @@ namespace lib {
RangeIter
operator++(int)
{
_maybe_throw();
return RangeIter (p_++,e_);
}
@ -361,6 +396,42 @@ namespace lib {
}
/**
* Helper for type rewritings:
* get the element type for an iterator like entity
*/
template<class TY>
struct IterType;
template<template<class,class> class Iter, class TY, class CON>
struct IterType<Iter<TY,CON> >
{
typedef CON Container;
typedef TY ElemType;
typedef typename RemovePtr<TY>::Type ValueType;
template<class T2>
struct SimilarIter
{
typedef Iter<T2,CON> Type;
};
};
template<class IT>
struct IterType<RangeIter<IT> >
: IterType<IT>
{
template<class T2>
struct SimilarIter ///< rebind to rewritten Iterator wrapped into RangeIter
{
typedef typename IterType<IT>::template SimilarIter<T2>::Type WrappedIter;
typedef RangeIter<WrappedIter> Type;
};
};
/**
* wrapper for an existing Iterator type,
* automatically dereferencing the output of the former.
@ -372,26 +443,56 @@ namespace lib {
class PtrDerefIter
: public lib::BoolCheckable<PtrDerefIter<IT> >
{
IT i_;
IT i_; ///< nested source iterator
public:
typedef typename IT::value_type pointer;
typedef typename IT::value_type pointer;
typedef typename RemovePtr<pointer>::Type value_type;
typedef value_type& reference;
typedef value_type& reference;
// the purpose of the following typedefs is to ease building a correct "const iterator"
typedef typename boost::remove_const<value_type>::type ValueTypeBase; // value_type without const
typedef typename IterType<IT>::template SimilarIter< ValueTypeBase* * >::Type WrappedIterType;
typedef typename IterType<IT>::template SimilarIter<const ValueTypeBase* * >::Type WrappedConstIterType;
typedef PtrDerefIter<WrappedIterType> IterType;
typedef PtrDerefIter<WrappedConstIterType> ConstIterType;
/** PtrDerefIter is always created
* by wrapping an existing iterator.
*/
PtrDerefIter (IT srcIter)
: i_(srcIter)
{ }
/** allow copy initialisation also
* when the base iter types are convertible */
template<class I2>
PtrDerefIter (I2 const& oIter)
: i_(reinterpret_cast<IT const&> (oIter.getBase())) /////////////////////////////TODO: properly guard this dangerous conversion by a traits template; the idea is to allow this conversion only for the initialisation of a "const iterator" from its sister type
/** allow copy initialisation also when
* the wrapped iterator is based on some variation of a pointer.
* Especially, this includes initialisation of the "const variant"
* from the "normal variant" of PtrDerefIter. Actually, we need to convert
* in this case by brute force, because indeed (const TY *)* is not assignable
* from (TY *)* -- just we know that our intention is to dereference both levels
* of pointers, and then the resulting conversion is correct.
* @note in case IT == WrappedIterType, this is just a redefinition of the
* default copy ctor. In all other cases, this is an <i>additional
* ctor besides the default copy ctor</i> */
PtrDerefIter (PtrDerefIter<WrappedIterType> const& oIter)
: i_(reinterpret_cast<IT const&> (oIter.getBase()))
{ }
PtrDerefIter&
operator= (PtrDerefIter<WrappedIterType> const& ref)
{
i_ = reinterpret_cast<IT const&> (ref.getBase());
}
/* === lumiera forward iterator concept === */
@ -450,28 +551,5 @@ namespace lib {
bool operator!= (PtrDerefIter<I1> const& il, PtrDerefIter<I2> const& ir) { return !(il == ir); }
/**
* Helper for type rewritings:
* get the element type for an iterator like entity
*/
template<class TY>
struct IterType;
template<template<class,class> class Iter, class TY, class CON>
struct IterType<Iter<TY,CON> >
{
typedef CON Container;
typedef TY ElemType;
typedef typename RemovePtr<TY>::Type Type;
template<class T2>
struct SimilarIter
{
typedef Iter<T2,CON> Type;
};
};
} // namespace lib
#endif

View file

@ -48,7 +48,6 @@
#include "include/logging.h"
#include "lib/iter-adapter.hpp"
#include "lib/error.hpp"
#include "lib/util.hpp"
#include <vector>
#include <boost/noncopyable.hpp>
@ -56,14 +55,13 @@
namespace lib {
using util::for_each;
/**
* Simple vector based collection of pointers, noncopyable and managing
* lifecycle of the pointed-to objects. Implemented by a vector of
* bare pointers (private inheritance)
* Simple vector based collection of pointers,
* managing lifecycle of the pointed-to objects.
* Implemented as a non-copyable object, based on a
* vector of bare pointers (private inheritance)
*/
template<class T>
class ScopedPtrVect
@ -72,11 +70,12 @@ namespace lib {
{
typedef std::vector<T*> _Vec;
typedef typename _Vec::iterator VIter;
// typedef typename _Vec::const_iterator VcIter;
typedef typename IterType<VIter>::template SimilarIter<const T**>::Type VcIter;
typedef RangeIter<VIter> RIter;
typedef RangeIter<VcIter> RcIter;
typedef PtrDerefIter<RIter> IterType;
typedef typename IterType::ConstIterType ConstIterType;
typedef typename IterType::WrappedConstIterType RcIter;
public:
@ -84,8 +83,6 @@ namespace lib {
typedef T & reference;
typedef T const& const_reference;
typedef typename IterType<VIter>::Type Tupe;
ScopedPtrVect ()
@ -154,8 +151,8 @@ namespace lib {
return *get(i);
}
typedef PtrDerefIter<RIter> iterator;
typedef PtrDerefIter<RcIter> const_iterator;
typedef IterType iterator;
typedef ConstIterType const_iterator;
iterator begin() { return iterator (allPtrs()); }
const_iterator begin() const { return const_iterator (allPtrs()); }

View file

@ -23,31 +23,27 @@
#include "lib/test/run.hpp"
#include "lib/test/test-helper.hpp"
#include "lib/util.hpp"
#include "lib/scoped-ptrvect.hpp"
#include "testdummy.hpp"
//////////////////////////////////////////////TODO test code
#include "lib/test/test-helper.hpp"
using lib::test::showSizeof;
#include <iostream>
using std::cout;
using std::endl;
//////////////////////////////////////////////TODO test code
namespace lib {
namespace test{
using ::Test;
using util::isnil;
using lumiera::error::LUMIERA_ERROR_ITER_EXHAUST;
typedef ScopedPtrVect<Dummy> VectD;
/********************************************************************
* @test ScopedPtrVect manages the lifecycle of a number of objects.
* @todo cover the const iterator and implement detaching of objects
* @todo implement detaching of objects
*/
class ScopedPtrVect_test : public Test
{
@ -118,12 +114,10 @@ namespace test{
++check;
++ii;
}
// Test the const iterator
check = 0;
///////////////////////////////////////////////////////////////////TODO test code
cout << showSizeof<VectD::Tupe> () << endl;
///////////////////////////////////////////////////////////////////TODO test code
VectD::const_iterator cii = holder.begin();
while (cii)
{
@ -131,6 +125,20 @@ namespace test{
++check;
++cii;
}
// Verify correct behaviour of iteration end
ASSERT (! (holder.end()));
ASSERT (isnil (holder.end()));
VERIFY_ERROR (ITER_EXHAUST, *holder.end() );
VERIFY_ERROR (ITER_EXHAUST, ++holder.end() );
ASSERT (ii == holder.end());
ASSERT (cii == holder.end());
VERIFY_ERROR (ITER_EXHAUST, ++ii );
VERIFY_ERROR (ITER_EXHAUST, ++cii );
}
ASSERT (0==checksum);
}