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:
Fischlurch 2026-03-25 23:51:32 +01:00
parent 68460d4900
commit fbda9baeb3
6 changed files with 84 additions and 47 deletions

View file

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

View file

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

View file

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

View file

@ -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
> >
{ }; { };

View file

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

View file

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