32 ->
decltype(std::integral_constant<std::size_t,std::tuple_size<T>::value>())
40 ->
decltype(std::integral_constant<std::size_t,T::size()>())
78constexpr auto size(
const T& t)
87 template<
class Container,
class Index,
88 std::enable_if_t<IsTuple<std::decay_t<Container>>::value,
int> = 0>
89 constexpr decltype(
auto) elementAt(Container&& c, Index&&,
PriorityTag<2>)
91 return std::get<std::decay_t<Index>::value>(c);
94 template<
class T, T... t,
class Index>
95 constexpr decltype(
auto) elementAt(std::integer_sequence<T, t...> c, Index, PriorityTag<1>)
100 template<
class Container,
class Index>
101 constexpr decltype(
auto) elementAt(Container&& c, Index&& i, PriorityTag<0>)
130template<
class Container,
class Index>
131constexpr decltype(
auto)
elementAt(Container&& c, Index&& i)
133 return Impl::elementAt(std::forward<Container>(c), std::forward<Index>(i),
PriorityTag<42>());
140 template<
class Begin,
class End,
142 constexpr auto integralRange(
const Begin& ,
const End& ,
const PriorityTag<1>&)
144 static_assert(Begin::value <= End::value,
"You cannot create an integralRange where end<begin");
148 template<
class Begin,
class End>
149 constexpr auto integralRange(
const Begin& begin,
const End& end,
const PriorityTag<0>&)
151 assert(begin<=end &&
"You cannot create an integralRange where end<begin");
176template<
class Begin,
class End>
206 constexpr void evaluateFoldExpression(std::initializer_list<T>&&)
209 template<
class Range,
class F,
class Index, Index... i>
210 constexpr void forEachIndex(Range&&
range, F&& f, std::integer_sequence<Index, i...>)
215 template<
class F,
class Index, Index... i>
216 constexpr void forEach(std::integer_sequence<Index, i...> , F&& f, PriorityTag<2>)
218 evaluateFoldExpression<int>({(f(std::integral_constant<Index,i>()), 0)...});
222 template<
class Range,
class F,
223 std::enable_if_t<IsIntegralConstant<decltype(Hybrid::size(std::declval<Range>()))>::value,
int> = 0>
224 constexpr void forEach(Range&&
range, F&& f, PriorityTag<1>)
227 auto indices = std::make_index_sequence<size>();
228 (forEachIndex)(std::forward<Range>(
range), std::forward<F>(f), indices);
231 template<
class Range,
class F>
232 constexpr void forEach(Range&&
range, F&& f, PriorityTag<0>)
234 for(
auto&& e :
range)
260template<
class Range,
class F>
283template<
class Range,
class T,
class F>
287 value = f(value, entry);
298 constexpr T operator()(T&& x)
const {
299 return std::forward<T>(x);
303 template<
class IfFunc,
class ElseFunc>
304 constexpr decltype(
auto) ifElse(std::true_type, IfFunc&& ifFunc, ElseFunc&& )
309 template<
class IfFunc,
class ElseFunc>
310 constexpr decltype(
auto) ifElse(std::false_type, IfFunc&& , ElseFunc&& elseFunc)
312 return elseFunc(Id{});
315 template<
class IfFunc,
class ElseFunc>
316 decltype(
auto) ifElse(
const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
321 return elseFunc(Id{});
348template<
class Condition,
class IfFunc,
class ElseFunc>
349decltype(
auto)
ifElse(
const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
351 return Impl::ifElse(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc));
361template<
class Condition,
class IfFunc>
362void ifElse(
const Condition& condition, IfFunc&& ifFunc)
364 ifElse(condition, std::forward<IfFunc>(ifFunc), [](
auto&&) {});
372 template<
class... Args>
373 constexpr decltype(
auto)
operator()(Args&&... args)
const
375 using T = std::common_type_t<Args...>;
376 return std::max({T(args)...});
381 template<
class... Args>
382 constexpr decltype(
auto)
operator()(Args&&... args)
const
384 using T = std::common_type_t<Args...>;
385 return std::min({T(args)...});
422template<
class Functor>
425 static_assert(std::is_default_constructible_v<Functor>,
426 "Operator in integral expressions shall be constexpr default constructible");
428 inline static constexpr Functor _functor = Functor{};
441 template<
class... Args>
442 constexpr decltype(
auto)
operator()(
const Args&... args)
const
444 if constexpr (std::conjunction_v<IsCompileTimeConstant<Args>...>)
446 constexpr auto result = _functor(Args::value...);
449 return std::integral_constant<std::remove_cv_t<
decltype(result)>,result>{};
454 return _functor(args...);
463template<
class Functor>
583 template<
class Result,
class T, T t0, T... tt,
class ValueType, ValueType value,
class Branches,
class ElseBranch>
584 constexpr Result switchCases(std::integer_sequence<T, t0, tt...>,
const std::integral_constant<ValueType, value>& , Branches&& branches, ElseBranch&& elseBranch)
592 if constexpr (((t0 == value) || ... || (tt == value)))
593 return branches(std::integral_constant<T, value>{});
599 template<
class Result,
class T,
class Value,
class Branches,
class ElseBranch>
600 constexpr Result switchCases(std::integer_sequence<T>,
const Value& , Branches&& , ElseBranch&& elseBranch)
605 template<
class Result,
class T, T t0, T... tt,
class Value,
class Branches,
class ElseBranch>
606 constexpr Result switchCases(std::integer_sequence<T, t0, tt...>,
const Value& value, Branches&& branches, ElseBranch&& elseBranch)
609 return branches(std::integral_constant<T, t0>());
611 return Impl::switchCases<Result>(std::integer_sequence<T, tt...>(), value, branches, elseBranch);
615 template <
class Result,
class T,
class Value,
class Branches,
class ElseBranch>
616 constexpr Result switchCases(IntegralRange<T>
range,
const Value& value, Branches&& branches, ElseBranch&& elseBranch)
618 return range.contains(value) ? branches(T(value)) : elseBranch();
622 template <
class Result,
class T, T to, T from,
class Value,
class Branches,
class ElseBranch>
623 constexpr Result switchCases(StaticIntegralRange<T, to, from>
range,
const Value& value, Branches&& branches, ElseBranch&& elseBranch)
625 using seq =
typename decltype(
range)::integer_sequence;
626 return Impl::switchCases<Result>(seq{}, value, branches, elseBranch);
660template<
class Cases,
class Value,
class Branches,
class ElseBranch>
661constexpr decltype(
auto)
switchCases(
const Cases& cases,
const Value& value, Branches&& branches, ElseBranch&& elseBranch)
663 return Impl::switchCases<decltype(elseBranch())>(cases, value, std::forward<Branches>(branches), std::forward<ElseBranch>(elseBranch));
685template<
class Cases,
class Value,
class Branches>
686constexpr void switchCases(
const Cases& cases,
const Value& value, Branches&& branches)
688 Impl::switchCases<void>(cases, value, std::forward<Branches>(branches),
689 []{ assert(
false &&
"value not found in range"); });
710template <
class T,
class Value,
class Branches>
713 assert(
range.contains(value) &&
"value not found in range");