#pragma once #include #include "../type/type.hpp" namespace util { template inline constexpr type::remove_reference_t &&move(T &&t) noexcept { return static_cast &&>(t); } template inline constexpr T &&forward(type::remove_reference_t &t) noexcept { return static_cast(t); } template inline constexpr T &&forward(type::remove_reference_t &&t) noexcept { static_assert(!type::is_lvalue_reference_v, "Can not forward an rvalue as an lvalue."); return static_cast(t); } template struct integer_sequence { using __type = integer_sequence; using value_type = T; static constexpr size_t size() noexcept { return sizeof...(Ints); } }; template using index_sequence = integer_sequence; namespace detail { template struct concat; template struct concat, integer_sequence> : integer_sequence { }; // uint64_t because this must be able to hold all possible sizes and cannot be T, because then the specialization for 0 // and 1 are not possible template struct gen_integer_sequence : detail::concat::__type, typename gen_integer_sequence::__type> { }; template struct gen_integer_sequence : integer_sequence { }; template struct gen_integer_sequence : integer_sequence { }; } // namespace detail template struct make_integer_sequence : detail::gen_integer_sequence { static_assert(N >= 0, "Integer sequence cannot be negative"); }; template using make_index_sequence = make_integer_sequence; template using index_sequence_for = make_index_sequence; // Not part of , but very useful namespace detail { template inline constexpr integer_sequence add_offset(integer_sequence) { return {}; } } // namespace detail template inline constexpr auto make_offset_integer_sequence() { return detail::add_offset(make_integer_sequence{}); } template inline constexpr auto make_offset_index_sequence() { return make_offset_integer_sequence(); } template void for_constexpr(Fn &&func, index_sequence) { (func(type::integral_constant{}), ...); } } // namespace util