tuple/value: allow calls to 'each' with empty tuples

This commit is contained in:
Danny Robson 2019-11-04 11:43:45 +11:00
parent f1f1a64845
commit df9902a0b5

View File

@ -18,24 +18,50 @@
namespace cruft::tuple::value { namespace cruft::tuple::value {
namespace detail {
// Call the function for the value at the index `S`, then increment
// the index and call ourselves again if we haven't reached the end.
//
// A detail function is used to simplify the case for empty tuples;
// ie, we'd like to keep the index assertion, but a constexpr-if won't
// elide the assertion.
template<
typename FunctionT,
typename TupleT,
std::size_t S = 0
>
void
each (FunctionT &&func, TupleT &&value)
{
using tuple_t = std::decay_t<TupleT>;
static_assert (S < std::tuple_size_v<tuple_t>);
std::invoke (func, std::get<S> (value));
if constexpr (S + 1 < std::tuple_size_v<tuple_t>) {
each<FunctionT,TupleT,S+1> (
std::forward<FunctionT> (func),
std::forward<TupleT> (value)
);
}
}
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
/// Call a provided functor of type FunctionT with each value in a /// Call a provided functor of type FunctionT with each value in a
/// provided tuple-like object TupleT /// provided tuple-like object TupleT
template< template<
typename FunctionT, typename FunctionT,
typename TupleT, typename TupleT
std::size_t S = 0
> >
void void
each (FunctionT &&func, TupleT &&value) each (FunctionT &&func, TupleT &&value)
{ {
using tuple_t = std::decay_t<TupleT>; if constexpr (std::tuple_size_v<std::decay_t<TupleT>> > 0) {
static_assert (S < std::tuple_size_v<tuple_t>); return detail::each (
std::forward<FunctionT> (func),
std::invoke (func, std::get<S> (value)); std::forward<TupleT> (value)
);
if constexpr (S + 1 < std::tuple_size_v<tuple_t>) {
each<FunctionT,TupleT,S+1> (std::forward<FunctionT> (func), std::forward<TupleT> (value));
} }
} }