Library: streamline value-type bindings
- use uniform naming scheme - extract type-binding from RangeIter into a trait-template - use the C++20 iterator concept and trait to detect a STL iterator
This commit is contained in:
parent
68460d4900
commit
fbda9baeb3
6 changed files with 84 additions and 47 deletions
|
|
@ -50,8 +50,8 @@ namespace lib {
|
||||||
|
|
||||||
using ResVal = decltype(data_->operator[](0));
|
using ResVal = decltype(data_->operator[](0));
|
||||||
|
|
||||||
using value_type = meta::RefTraits<ResVal>::Value;
|
using value_type = meta::RefTraits<ResVal>::value_type;
|
||||||
using reference = meta::RefTraits<ResVal>::Reference;
|
using reference = meta::RefTraits<ResVal>::reference;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
checkPoint() const
|
checkPoint() const
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,9 @@ namespace util { // see lib/util.hpp
|
||||||
|
|
||||||
namespace lib {
|
namespace lib {
|
||||||
|
|
||||||
|
using std::is_pointer_v;
|
||||||
|
using std::remove_pointer_t;
|
||||||
|
using std::remove_reference_t;
|
||||||
|
|
||||||
namespace { // internal helpers
|
namespace { // internal helpers
|
||||||
inline void
|
inline void
|
||||||
|
|
@ -149,6 +152,13 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
namespace iter {
|
namespace iter {
|
||||||
|
using meta::is_StateCore;
|
||||||
|
using meta::can_IterForEach;
|
||||||
|
using meta::can_STL_ForEach;
|
||||||
|
using meta::ValueTypeBinding;
|
||||||
|
using meta::RefTraits;
|
||||||
|
|
||||||
|
|
||||||
/** type binding helper: an iterato's actual result type */
|
/** type binding helper: an iterato's actual result type */
|
||||||
template<class IT>
|
template<class IT>
|
||||||
using Yield = decltype(std::declval<IT>().operator*());
|
using Yield = decltype(std::declval<IT>().operator*());
|
||||||
|
|
@ -157,6 +167,34 @@ namespace lib {
|
||||||
template<class COR>
|
template<class COR>
|
||||||
using CoreYield = decltype(std::declval<COR>().yield());
|
using CoreYield = decltype(std::declval<COR>().yield());
|
||||||
|
|
||||||
|
|
||||||
|
template<class IT>
|
||||||
|
concept legacy_traits_marked = requires
|
||||||
|
{
|
||||||
|
typename std::iterator_traits<IT>::value_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class IT>
|
||||||
|
concept stl_iter = std::input_iterator<IT> or legacy_traits_marked<IT>;
|
||||||
|
|
||||||
|
|
||||||
|
/** Iterator-Traits: definitions to level the difference between
|
||||||
|
* Lumiera-Iterators and the STL usage of ranges / iterators.
|
||||||
|
*/
|
||||||
|
template<class IT>
|
||||||
|
struct Trait
|
||||||
|
{
|
||||||
|
static constexpr bool is_LumieraIter = can_IterForEach<IT>::value;
|
||||||
|
static constexpr bool is_STLIter = stl_iter<IT>;
|
||||||
|
|
||||||
|
// static_assert(is_LumieraIter or is_STLIter);
|
||||||
|
|
||||||
|
using _ValTrait = std::conditional_t<is_LumieraIter, ValueTypeBinding<IT>
|
||||||
|
, RefTraits<std::iter_reference_t<IT>>>;
|
||||||
|
using value_type = _ValTrait::value_type;
|
||||||
|
using reference = _ValTrait::reference;
|
||||||
|
using pointer = _ValTrait::pointer;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -302,7 +340,7 @@ namespace lib {
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using ConRef = meta::RefTraits<CON>::Reference;
|
using ConRef = meta::RefTraits<CON>::reference;
|
||||||
|
|
||||||
/** allow derived classes to access backing container */
|
/** allow derived classes to access backing container */
|
||||||
ConRef source() { return source_; }
|
ConRef source() { return source_; }
|
||||||
|
|
@ -376,9 +414,9 @@ namespace lib {
|
||||||
ST core_;
|
ST core_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = meta::RefTraits<T>::Value;
|
using value_type = meta::RefTraits<T>::value_type;
|
||||||
using reference = meta::RefTraits<T>::Reference;
|
using reference = meta::RefTraits<T>::reference;
|
||||||
using pointer = meta::RefTraits<T>::Pointer;
|
using pointer = meta::RefTraits<T>::pointer;
|
||||||
|
|
||||||
IterStateWrapper (ST&& initialState)
|
IterStateWrapper (ST&& initialState)
|
||||||
: core_(std::forward<ST>(initialState))
|
: core_(std::forward<ST>(initialState))
|
||||||
|
|
@ -500,7 +538,7 @@ namespace lib {
|
||||||
class IterStateCore
|
class IterStateCore
|
||||||
: public IT
|
: public IT
|
||||||
{
|
{
|
||||||
static_assert (lib::meta::can_IterForEach<IT>::value
|
static_assert (iter::can_IterForEach<IT>::value
|
||||||
,"Lumiera Iterator required as source");
|
,"Lumiera Iterator required as source");
|
||||||
protected:
|
protected:
|
||||||
IT&
|
IT&
|
||||||
|
|
@ -545,7 +583,7 @@ namespace lib {
|
||||||
class CheckedCore
|
class CheckedCore
|
||||||
: public COR
|
: public COR
|
||||||
{
|
{
|
||||||
static_assert (lib::meta::is_StateCore<COR>::value
|
static_assert (iter::is_StateCore<COR>::value
|
||||||
,"Adapted type must expose a »state core« API");
|
,"Adapted type must expose a »state core« API");
|
||||||
protected:
|
protected:
|
||||||
COR&
|
COR&
|
||||||
|
|
@ -694,9 +732,9 @@ namespace lib {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using YieldRes = iter::CoreYield<COR>;
|
using YieldRes = iter::CoreYield<COR>;
|
||||||
using value_type = meta::RefTraits<YieldRes>::Value;
|
using value_type = meta::RefTraits<YieldRes>::value_type;
|
||||||
using reference = meta::RefTraits<YieldRes>::Reference;
|
using reference = meta::RefTraits<YieldRes>::reference;
|
||||||
using pointer = meta::RefTraits<YieldRes>::Pointer;
|
using pointer = meta::RefTraits<YieldRes>::pointer;
|
||||||
|
|
||||||
|
|
||||||
/** by default, pass anything down for initialisation of the core.
|
/** by default, pass anything down for initialisation of the core.
|
||||||
|
|
@ -805,16 +843,12 @@ namespace lib {
|
||||||
IT p_;
|
IT p_;
|
||||||
IT e_;
|
IT e_;
|
||||||
|
|
||||||
static constexpr bool _is_LumieraIter = meta::can_IterForEach<IT>::value;
|
|
||||||
using _ValTrait = std::conditional_t<_is_LumieraIter, meta::ValueTypeBinding<IT>
|
|
||||||
, meta::ValueTypeBinding<meta::remove_pointer_t<IT>>>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using pointer = _ValTrait::pointer;
|
using pointer = iter::Trait<IT>::pointer;
|
||||||
using reference = _ValTrait::reference;
|
using reference = iter::Trait<IT>::reference;
|
||||||
|
|
||||||
/// @note special twist, since a STL const_iterator would yield a non-const `value_type`
|
/// @note special twist, since a STL const_iterator would yield a non-const `value_type`
|
||||||
using value_type = std::remove_reference<reference>::type;
|
using value_type = std::remove_reference_t<reference>;
|
||||||
|
|
||||||
|
|
||||||
RangeIter (IT const& start, IT const& end)
|
RangeIter (IT const& start, IT const& end)
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ namespace lib {
|
||||||
struct _DecoratorTraits<SRC, enable_if<is_StateCore<SRC>>>
|
struct _DecoratorTraits<SRC, enable_if<is_StateCore<SRC>>>
|
||||||
{
|
{
|
||||||
using SrcRaw = lib::meta::Strip<SRC>::Type;
|
using SrcRaw = lib::meta::Strip<SRC>::Type;
|
||||||
using SrcVal = meta::RefTraits<iter::CoreYield<SrcRaw>>::Value;
|
using SrcVal = meta::RefTraits<iter::CoreYield<SrcRaw>>::value_type;
|
||||||
using SrcIter = lib::IterableDecorator<lib::CheckedCore<SrcRaw>>;
|
using SrcIter = lib::IterableDecorator<lib::CheckedCore<SrcRaw>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -478,7 +478,7 @@ namespace lib {
|
||||||
struct _ReduceTraits
|
struct _ReduceTraits
|
||||||
{
|
{
|
||||||
using Result = iter_explorer::_FunTraits<FUN,SRC>::Res;
|
using Result = iter_explorer::_FunTraits<FUN,SRC>::Res;
|
||||||
using ResVal = lib::meta::RefTraits<Result>::Value;
|
using ResVal = lib::meta::RefTraits<Result>::value_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1038,9 +1038,9 @@ namespace lib {
|
||||||
Aggregator aggregate_;
|
Aggregator aggregate_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = meta::RefTraits<AGG>::Value;
|
using value_type = meta::RefTraits<AGG>::value_type;
|
||||||
using reference = meta::RefTraits<AGG>::Reference;
|
using reference = meta::RefTraits<AGG>::reference;
|
||||||
using pointer = meta::RefTraits<AGG>::Pointer;
|
using pointer = meta::RefTraits<AGG>::pointer;
|
||||||
|
|
||||||
GroupAggregator() =default;
|
GroupAggregator() =default;
|
||||||
// inherited default copy operations
|
// inherited default copy operations
|
||||||
|
|
@ -1698,6 +1698,9 @@ namespace lib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto
|
||||||
|
flatten();
|
||||||
|
|
||||||
/** adapt this IterExplorer to pipe each result value through a transformation function.
|
/** adapt this IterExplorer to pipe each result value through a transformation function.
|
||||||
* Several "layers" of mapping can be piled on top of each other, possibly mixed with the
|
* Several "layers" of mapping can be piled on top of each other, possibly mixed with the
|
||||||
* other types of adaptation, like the child-expanding operation, or a filter. Obviously,
|
* other types of adaptation, like the child-expanding operation, or a filter. Obviously,
|
||||||
|
|
@ -1760,7 +1763,7 @@ namespace lib {
|
||||||
|
|
||||||
static_assert (meta::is_BinaryFun<FAGG>());
|
static_assert (meta::is_BinaryFun<FAGG>());
|
||||||
using ArgType1 = _Fun<FAGG>::Args::List::Head;
|
using ArgType1 = _Fun<FAGG>::Args::List::Head;
|
||||||
using Aggregate = meta::RefTraits<ArgType1>::Value;
|
using Aggregate = meta::RefTraits<ArgType1>::value_type;
|
||||||
|
|
||||||
using ResCore = iter_explorer::GroupAggregator<SRC, Aggregate, GroupVal>;
|
using ResCore = iter_explorer::GroupAggregator<SRC, Aggregate, GroupVal>;
|
||||||
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
using ResIter = _DecoratorTraits<ResCore>::SrcIter;
|
||||||
|
|
|
||||||
|
|
@ -258,33 +258,33 @@ namespace meta {
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
struct RefTraits
|
struct RefTraits
|
||||||
{
|
{
|
||||||
typedef TY Value;
|
typedef TY value_type;
|
||||||
typedef TY* Pointer;
|
typedef TY& reference;
|
||||||
typedef TY& Reference;
|
typedef TY* pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
struct RefTraits<TY *>
|
struct RefTraits<TY *>
|
||||||
{
|
{
|
||||||
typedef TY* Value;
|
typedef TY* value_type;
|
||||||
typedef TY** Pointer;
|
typedef TY*& reference;
|
||||||
typedef TY*& Reference;
|
typedef TY** pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
struct RefTraits<TY &>
|
struct RefTraits<TY &>
|
||||||
{
|
{
|
||||||
typedef TY Value;
|
typedef TY value_type;
|
||||||
typedef TY* Pointer;
|
typedef TY& reference;
|
||||||
typedef TY& Reference;
|
typedef TY* pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
struct RefTraits<TY &&>
|
struct RefTraits<TY &&>
|
||||||
{
|
{
|
||||||
typedef TY Value;
|
typedef TY value_type;
|
||||||
typedef TY* Pointer;
|
typedef TY& reference;
|
||||||
typedef TY& Reference;
|
typedef TY* pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -327,8 +327,8 @@ namespace meta {
|
||||||
/** verify the first (special) type can stand-in for the second */
|
/** verify the first (special) type can stand-in for the second */
|
||||||
template<typename S, typename G>
|
template<typename S, typename G>
|
||||||
struct can_StandIn
|
struct can_StandIn
|
||||||
: std::is_convertible<typename RefTraits<S>::Reference
|
: std::is_convertible<typename RefTraits<S>::reference
|
||||||
,typename RefTraits<G>::Reference
|
,typename RefTraits<G>::reference
|
||||||
>
|
>
|
||||||
{ };
|
{ };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,16 +107,16 @@ namespace meta {
|
||||||
template<typename TY, typename SEL =void>
|
template<typename TY, typename SEL =void>
|
||||||
struct ValueTypeBinding
|
struct ValueTypeBinding
|
||||||
{
|
{
|
||||||
using value_type = RefTraits<TY>::Value;
|
using value_type = RefTraits<TY>::value_type;
|
||||||
using reference = RefTraits<TY>::Reference;
|
using reference = RefTraits<TY>::reference;
|
||||||
using pointer = RefTraits<TY>::Pointer;
|
using pointer = RefTraits<TY>::pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** specialisation for classes providing STL style type binding definitions */
|
/** specialisation for classes providing STL style type binding definitions */
|
||||||
template<typename TY>
|
template<typename TY>
|
||||||
struct ValueTypeBinding<TY, enable_if<use_ValueTypebindings<TY>> >
|
struct ValueTypeBinding<TY, enable_if<use_ValueTypebindings<TY>> >
|
||||||
{
|
{
|
||||||
using _SrcType = RefTraits<TY>::Value;
|
using _SrcType = RefTraits<TY>::value_type;
|
||||||
|
|
||||||
using value_type = _SrcType::value_type;
|
using value_type = _SrcType::value_type;
|
||||||
using reference = _SrcType::reference;
|
using reference = _SrcType::reference;
|
||||||
|
|
@ -159,9 +159,9 @@ namespace meta {
|
||||||
>;
|
>;
|
||||||
|
|
||||||
using ResType = _ValRef;
|
using ResType = _ValRef;
|
||||||
using value_type = RefTraits<ResType>::Value;
|
using value_type = RefTraits<ResType>::value_type;
|
||||||
using reference = RefTraits<ResType>::Reference;
|
using reference = RefTraits<ResType>::reference;
|
||||||
using pointer = RefTraits<ResType>::Pointer;
|
using pointer = RefTraits<ResType>::pointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,8 +231,8 @@ namespace lib {
|
||||||
friend auto begin (Several const& svl) { return svl.begin();}
|
friend auto begin (Several const& svl) { return svl.begin();}
|
||||||
friend auto end (Several const& svl) { return svl.end(); }
|
friend auto end (Several const& svl) { return svl.end(); }
|
||||||
|
|
||||||
using value_type = meta::RefTraits<I>::Value;
|
using value_type = meta::RefTraits<I>::value_type;
|
||||||
using reference = meta::RefTraits<I>::Reference;
|
using reference = meta::RefTraits<I>::reference;
|
||||||
using const_reference = value_type const&;
|
using const_reference = value_type const&;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue