Upgrade: switch existing usages of forEachIDX
...to rely on the new formulation and the extended template `WithIdxSeq` This is in preparation to use this new iteration scheme also from the tuple_like concept
This commit is contained in:
parent
49e7b31511
commit
bb0b73e2a7
2 changed files with 62 additions and 110 deletions
|
|
@ -244,23 +244,56 @@ namespace meta {
|
||||||
|
|
||||||
/** helper to invoke a functor, passing instances of std::integral_constant
|
/** helper to invoke a functor, passing instances of std::integral_constant
|
||||||
* @tparam N size of the index-sequence to use for instantiation
|
* @tparam N size of the index-sequence to use for instantiation
|
||||||
|
* @remark the functor is given for...
|
||||||
|
* - to be invoked either (as void) for each index
|
||||||
|
* - or as a predicate, combining the results with AND / OR
|
||||||
*/
|
*/
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
class WithIdxSeq
|
class WithIdxSeq
|
||||||
{
|
{
|
||||||
template<class FUN, size_t...idx>
|
template<class FUN, size_t...idx>
|
||||||
static void
|
static constexpr void
|
||||||
invoke (FUN&& fun, std::index_sequence<idx...>)
|
invoke_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||||
{
|
{
|
||||||
(fun (std::integral_constant<size_t,idx>{}), ...);
|
(fun (std::integral_constant<size_t,idx>{}), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class FUN, size_t...idx>
|
||||||
|
static constexpr bool
|
||||||
|
and_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||||
|
{
|
||||||
|
return (fun (std::integral_constant<size_t,idx>{}) and ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FUN, size_t...idx>
|
||||||
|
static constexpr bool
|
||||||
|
or_forEach (FUN&& fun, std::index_sequence<idx...>)
|
||||||
|
{
|
||||||
|
return (fun (std::integral_constant<size_t,idx>{}) or ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
using IdxSeq = std::make_index_sequence<N>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<class FUN>
|
template<class FUN>
|
||||||
static void
|
static constexpr void
|
||||||
invoke (FUN&& fun)
|
invoke (FUN&& fun)
|
||||||
{
|
{
|
||||||
invoke (std::forward<FUN>(fun), std::make_index_sequence<N>{});
|
invoke_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FUN>
|
||||||
|
static constexpr bool
|
||||||
|
andAll (FUN&& fun)
|
||||||
|
{
|
||||||
|
return and_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class FUN>
|
||||||
|
static constexpr bool
|
||||||
|
orAny (FUN&& fun)
|
||||||
|
{
|
||||||
|
return or_forEach (std::forward<FUN>(fun), IdxSeq{});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -268,30 +301,31 @@ namespace meta {
|
||||||
* Invoke a function (or λ) with index numbers derived from some variadic count.
|
* Invoke a function (or λ) with index numbers derived from some variadic count.
|
||||||
* Notably this construct can be used for compile-time iteration over a structure.
|
* Notably this construct can be used for compile-time iteration over a structure.
|
||||||
* Instances of `std::integral_constant` are passed in sequence to the functor.
|
* Instances of `std::integral_constant` are passed in sequence to the functor.
|
||||||
* The _size_ of the index sequence is derived from the following sources
|
* The _size_ of the index sequence is derived using a \ref ElmTypes specialisation
|
||||||
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
|
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
|
||||||
* - otherwise, if the type is a loki-style type sequence or type list,
|
* - otherwise, if the type is a _type sequence_ (`Types<T...>`), then
|
||||||
* the number of type nodes is used
|
* the size of this meta sequence is used
|
||||||
* - otherwise, as fall-back the number of template parameters is used
|
* - otherwise, sequence-size ≡ 1 is used as fall-back
|
||||||
*/
|
*/
|
||||||
template<class TTX, class FUN>
|
template<class TTX, class FUN>
|
||||||
inline void
|
inline void
|
||||||
forEachIDX (FUN&& fun)
|
forEachIDX (FUN&& fun)
|
||||||
{
|
{
|
||||||
auto N = []{
|
WithIdxSeq<ElmTypes<TTX>::SIZ>::invoke (std::forward<FUN> (fun));
|
||||||
if constexpr (is_Structured<TTX>())
|
}
|
||||||
return size_t(std::tuple_size<TTX>::value);
|
|
||||||
else
|
template<class TTX, class FUN>
|
||||||
if constexpr (lib::meta::is_Typelist<TTX>::value)
|
inline bool
|
||||||
return lib::meta::count<typename TTX::List>();
|
andAllIDX (FUN&& fun)
|
||||||
else
|
{
|
||||||
{ // Fallback: rebind template arguments into a type sequence
|
return WithIdxSeq<ElmTypes<TTX>::SIZ>::andAll (std::forward<FUN> (fun));
|
||||||
using Seq = typename RebindVariadic<Types, TTX>::Type;
|
}
|
||||||
return size_t(count<Seq>());
|
|
||||||
}
|
template<class TTX, class FUN>
|
||||||
};
|
inline bool
|
||||||
|
orAnyIDX (FUN&& fun)
|
||||||
WithIdxSeq<N()>::invoke (std::forward<FUN> (fun));
|
{
|
||||||
|
return WithIdxSeq<ElmTypes<TTX>::SIZ>::orAny (std::forward<FUN> (fun));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,88 +62,6 @@ namespace test {
|
||||||
|
|
||||||
} // (End) test data
|
} // (End) test data
|
||||||
|
|
||||||
////////////////////////////////////////OOO
|
|
||||||
template<class TTX>
|
|
||||||
class WithIdxSeq2
|
|
||||||
{
|
|
||||||
template<class FUN, size_t...idx>
|
|
||||||
static void
|
|
||||||
invoke_forEach (FUN&& fun, std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
(fun (std::integral_constant<size_t,idx>{}), ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class FUN, size_t...idx>
|
|
||||||
static bool
|
|
||||||
and_forEach (FUN&& fun, std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
return (fun (std::integral_constant<size_t,idx>{}) and ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class FUN, size_t...idx>
|
|
||||||
static bool
|
|
||||||
or_forEach (FUN&& fun, std::index_sequence<idx...>)
|
|
||||||
{
|
|
||||||
return (fun (std::integral_constant<size_t,idx>{}) or ...);
|
|
||||||
}
|
|
||||||
|
|
||||||
using IdxSeq = typename ElmTypes<TTX>::Idx;
|
|
||||||
|
|
||||||
public:
|
|
||||||
template<class FUN>
|
|
||||||
static void
|
|
||||||
invoke (FUN&& fun)
|
|
||||||
{
|
|
||||||
invoke_forEach (std::forward<FUN>(fun), IdxSeq{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class FUN>
|
|
||||||
static bool
|
|
||||||
andAll (FUN&& fun)
|
|
||||||
{
|
|
||||||
return and_forEach (std::forward<FUN>(fun), IdxSeq{});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class FUN>
|
|
||||||
static bool
|
|
||||||
orAny (FUN&& fun)
|
|
||||||
{
|
|
||||||
return or_forEach (std::forward<FUN>(fun), IdxSeq{});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoke a function (or λ) with index numbers derived from some variadic count.
|
|
||||||
* Notably this construct can be used for compile-time iteration over a structure.
|
|
||||||
* Instances of `std::integral_constant` are passed in sequence to the functor.
|
|
||||||
* The _size_ of the index sequence is derived from the following sources
|
|
||||||
* - if the type \a TTX is _tuple-like,_ then std::tuple_size<TTX> is used
|
|
||||||
* - otherwise, if the type is a loki-style type sequence or type list,
|
|
||||||
* the number of type nodes is used
|
|
||||||
* - otherwise, as fall-back the number of template parameters is used
|
|
||||||
*/
|
|
||||||
template<class TTX, class FUN>
|
|
||||||
inline void
|
|
||||||
forEachIDX2 (FUN&& fun)
|
|
||||||
{
|
|
||||||
WithIdxSeq2<TTX>::invoke (std::forward<FUN> (fun));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TTX, class FUN>
|
|
||||||
inline bool
|
|
||||||
andAllIDX2 (FUN&& fun)
|
|
||||||
{
|
|
||||||
return WithIdxSeq2<TTX>::andAll (std::forward<FUN> (fun));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class TTX, class FUN>
|
|
||||||
inline bool
|
|
||||||
orAnyIDX2 (FUN&& fun)
|
|
||||||
{
|
|
||||||
return WithIdxSeq2<TTX>::orAny (std::forward<FUN> (fun));
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////OOO
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
|
|
@ -280,7 +198,7 @@ namespace test {
|
||||||
_Fmt showElm{"|%d|▷%s◁"};
|
_Fmt showElm{"|%d|▷%s◁"};
|
||||||
dump = "";
|
dump = "";
|
||||||
// apply λ-generic with (constexpr) index
|
// apply λ-generic with (constexpr) index
|
||||||
forEachIDX2<Tup> ([&](auto idx)
|
forEachIDX<Tup> ([&](auto idx)
|
||||||
{
|
{
|
||||||
using Idx = decltype(idx);
|
using Idx = decltype(idx);
|
||||||
using Iii = std::integral_constant<size_t, idx.value>;
|
using Iii = std::integral_constant<size_t, idx.value>;
|
||||||
|
|
@ -293,16 +211,16 @@ namespace test {
|
||||||
// apply λ-generic and combine results
|
// apply λ-generic and combine results
|
||||||
auto boolFun = [&](auto idx){ return bool(get<idx>(tup)); };
|
auto boolFun = [&](auto idx){ return bool(get<idx>(tup)); };
|
||||||
|
|
||||||
CHECK ( andAllIDX2<Tup> (boolFun));
|
CHECK ( andAllIDX<Tup> (boolFun));
|
||||||
get<0>(tup) = 0; // ◁————————————————————— demonstrate that a run-time evaluation happens
|
get<0>(tup) = 0; // ◁————————————————————— demonstrate that a run-time evaluation happens
|
||||||
CHECK (not andAllIDX2<Tup> (boolFun));
|
CHECK (not andAllIDX<Tup> (boolFun));
|
||||||
CHECK ( orAnyIDX2<Tup> (boolFun));
|
CHECK ( orAnyIDX<Tup> (boolFun));
|
||||||
|
|
||||||
// can use this mechanism also for sole compile-time computation
|
// can use this mechanism also for sole compile-time computation
|
||||||
auto integralCheckFun = [](auto idx){ return std::is_integral_v<std::tuple_element_t<idx,Tup>>;};
|
auto integralCheckFun = [](auto idx){ return std::is_integral_v<std::tuple_element_t<idx,Tup>>;};
|
||||||
|
|
||||||
CHECK (not andAllIDX2<Tup> (integralCheckFun));
|
CHECK (not andAllIDX<Tup> (integralCheckFun));
|
||||||
CHECK ( orAnyIDX2<Tup> (integralCheckFun));
|
CHECK ( orAnyIDX<Tup> (integralCheckFun));
|
||||||
|
|
||||||
// Note however, the same can also be achieved simpler,
|
// Note however, the same can also be achieved simpler,
|
||||||
// using any meta-function which takes a single type argument...
|
// using any meta-function which takes a single type argument...
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue