Library: a stricter criterion for Lumiera iterators
On occasion of the recent improvements, I noticed that somewhere in the past I had misunderstood the meaning of the typedefs in iterators: * `reference` is the central definition; this is what the iterator yields * `value_type` is secondary; this is the type you use to store results So at times I defined only a `value_type`, wrongly assuming this to be the primary definition, and all the other ones to be ephemeral. Consequently the trait to detect a »Lumiera Forward Iterator« should be sharpened... ...which unveils a long-standing bug in our ''Duck Detector'' (it is not possible to define a pointer to a reference, causing a check for the `reference` typedef erroneously to fail.
This commit is contained in:
parent
fbda9baeb3
commit
f05402c04e
3 changed files with 27 additions and 13 deletions
|
|
@ -90,15 +90,18 @@ namespace iter_stl {
|
|||
|
||||
|
||||
/**
|
||||
* helper baseclass to simplify
|
||||
* defining customised wrapped STL iterators
|
||||
* @internal helper baseclass to simplify defining customised wrapped STL iterators.
|
||||
* @remark this is meant to be compliant to a STL input-iterator;
|
||||
* it's _not_ a »Lumiera Forward Iterator« (lacks the bool check for iteration end)
|
||||
* @warning minimal definition, since it is only intended to be wrapped into lib::RangeIter
|
||||
*/
|
||||
template<typename DEF>
|
||||
struct WrappedStlIter : DEF
|
||||
{
|
||||
using Iter = DEF::Iter;
|
||||
using reference = DEF::reference;
|
||||
using pointer = DEF::pointer;
|
||||
using Iter = DEF::Iter;
|
||||
using value_type = DEF::value_type;
|
||||
using reference = DEF::reference;
|
||||
using pointer = DEF::pointer;
|
||||
|
||||
|
||||
WrappedStlIter() : i_() { }
|
||||
|
|
@ -112,6 +115,10 @@ namespace iter_stl {
|
|||
friend bool operator== (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ == i2.i_; }
|
||||
friend bool operator!= (WrappedStlIter const& i1, WrappedStlIter const& i2) { return i1.i_ != i2.i_; }
|
||||
|
||||
/** @note the following dummy definitions are required to fulfil the concept std::input_iterator */
|
||||
WrappedStlIter& operator++(int) { NOTREACHED("never used as STL iterator"); return *this; }
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
private:
|
||||
mutable Iter i_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -108,13 +108,15 @@
|
|||
* and check the static bool value field.
|
||||
* @warning none of these checks can detect private members
|
||||
*/
|
||||
#define META_DETECT_NESTED(_TYPE_) \
|
||||
template<typename TY> \
|
||||
class HasNested_##_TYPE_ \
|
||||
{ \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(X::_TYPE_ *); \
|
||||
#define META_DETECT_NESTED(_TYPE_) \
|
||||
template<typename TY> \
|
||||
class HasNested_##_TYPE_ \
|
||||
{ \
|
||||
\
|
||||
template<class X \
|
||||
,typename = std::void_t<typename X::_TYPE_> \
|
||||
> \
|
||||
static Yes_t check(int); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
|
|
|
|||
|
|
@ -493,19 +493,24 @@ namespace meta {
|
|||
* This is just a heuristic, based on some common properties
|
||||
* of such iterators; it is enough to distinguish it from an
|
||||
* STL container, but can certainly be refined.
|
||||
* @note deliberately a Lumiera iterator does _not fulfil_
|
||||
* the concept std::input_iterator. And vice versa:
|
||||
* a STL iterator lacks the `bool` check for iteration end.
|
||||
*/
|
||||
template<typename T>
|
||||
class can_IterForEach
|
||||
{
|
||||
using Type = Strip<T>::Type;
|
||||
using Type = Strip<T>::TypeReferred;
|
||||
|
||||
META_DETECT_NESTED(value_type);
|
||||
META_DETECT_NESTED(reference);
|
||||
META_DETECT_OPERATOR_DEREF();
|
||||
META_DETECT_OPERATOR_INC();
|
||||
|
||||
public:
|
||||
enum{ value = std::is_constructible<bool, Type>::value
|
||||
and HasNested_value_type<Type>::value
|
||||
and HasNested_reference<Type>::value
|
||||
and HasOperator_deref<Type>::value
|
||||
and HasOperator_inc<Type>::value
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue