DiffMessage: reshape IterAdapter to allow for custom diagnostics

since we do not want to increase the footprint, we're bound to reuse
an existing VTable -- so IterAdapter itself is our only option.
Unfortunately we'll need to pass that through one additional
decoration layer, which is here the iterator; to be able to
add our string conversion there, we need to turn that into
a derived class and add a call to access the underlying
container, which gets us into element type definition mess....
This commit is contained in:
Fischlurch 2017-08-11 16:56:18 +02:00
parent 88b2260496
commit dfd3dc1275
3 changed files with 66 additions and 9 deletions

View file

@ -245,6 +245,18 @@ namespace lib {
// for comparison with IterAdapter{}
protected:
using ConRef = typename iter::TypeBinding<CON>::reference;
/** allow derived classes to
* access backing container */
ConRef
source()
{
return source_;
}
private:
void
_maybe_throw() const

View file

@ -32,7 +32,7 @@
** \par Standard Adapters
** As a complement, this header contains a generic implementation
** of the IterSource interface by wrapping an existing Lumiera Forward Iterator.
** Using this WrappedLumieraIterator, the details of this wrapped source iterator
** Using this WrappedLumieraIter, the details of this wrapped source iterator
** remain opaque. To ease the use of this adapter, a selection of free functions
** is provided, allowing to build opaque "all elements" or "all keys" iterators
** for various STL containers.
@ -53,6 +53,7 @@
#include <boost/type_traits/remove_const.hpp>
#include <boost/noncopyable.hpp>
#include <string>
#include <memory>
@ -60,6 +61,7 @@
namespace lib {
using std::string;
using std::shared_ptr;
@ -107,7 +109,14 @@ namespace lib {
public:
virtual ~IterSource() { }; ///< is ABC
virtual ~IterSource() { }; ///< is ABC
virtual
operator string() const ///< subclasses may offer diagnostics
{
return "IterSource(opaque)";
}
/* == Iteration control API for IterAdapter frontend == */
@ -127,7 +136,14 @@ namespace lib {
/* == public builder API to create instances == */
typedef IterAdapter<Pos, DataHandle> iterator;
struct iterator
: IterAdapter<Pos, DataHandle>
{
using _I = IterAdapter<Pos, DataHandle>
;
using _I::IterAdapter;
operator string() const {return _I::source()? string(*_I::source()) : ""; }
};
/** build an iterator frontend for the given source,
* @note the source is allocated separately and
@ -203,7 +219,7 @@ namespace lib {
* erasing the specific type information of the template parameter IT
*/
template<class IT>
class WrappedLumieraIterator
class WrappedLumieraIter
: public IterSource<typename IT::value_type>
, boost::noncopyable
{
@ -235,7 +251,7 @@ namespace lib {
public:
WrappedLumieraIterator (IT const& orig)
WrappedLumieraIter (IT const& orig)
: src_(orig)
{ }
};
@ -333,7 +349,7 @@ namespace lib {
{
typedef typename _IterT<IT>::Val ValType;
return IterSource<ValType>::build (new WrappedLumieraIterator<IT> (source));
return IterSource<ValType>::build (new WrappedLumieraIter<IT> (source));
}
@ -354,7 +370,7 @@ namespace lib {
typedef typename _TransformIterT<IT,FUN>::TransIter TransIT;
return IterSource<ValType>::build (
new WrappedLumieraIterator<TransIT> (
new WrappedLumieraIter<TransIT> (
transformIterator (source, processingFunc)));
}
@ -434,7 +450,7 @@ namespace lib {
typedef RangeIter<typename CON::iterator> Range;
Range contents (container.begin(), container.end());
return IterSource<ValType>::build (new WrappedLumieraIterator<Range>(contents));
return IterSource<ValType>::build (new WrappedLumieraIter<Range>(contents));
}
@ -449,7 +465,7 @@ namespace lib {
typedef RangeIter<IT> Range;
Range contents (begin, end);
return IterSource<ValType>::build (new WrappedLumieraIterator<Range>(contents));
return IterSource<ValType>::build (new WrappedLumieraIter<Range>(contents));
}
}

View file

@ -43,6 +43,11 @@
namespace std {
template<typename _Tp>
class shared_ptr;
}
namespace lib {
namespace iter {
@ -78,6 +83,30 @@ namespace iter {
typedef const TY* pointer;
};
template<typename TY>
struct TypeBinding<TY &>
{
typedef TY value_type;
typedef TY& reference;
typedef TY* pointer;
};
template<typename TY>
struct TypeBinding<TY const&>
{
typedef TY value_type;
typedef const TY& reference;
typedef const TY* pointer;
};
template<typename TY>
struct TypeBinding<std::shared_ptr<TY>>
{
typedef TY value_type;
typedef const TY& reference;
typedef const TY* pointer;
};
}} // namespace lib