diff --git a/docs/utility.adoc b/docs/utility.adoc index a83d8ad..2e742a9 100644 --- a/docs/utility.adoc +++ b/docs/utility.adoc @@ -116,6 +116,49 @@ std::uint32_t i; assert(stdx::is_aligned_with(&i)); ---- +=== `make_integer_sequence` + +`make_integer_sequence` is a class template that derives from +https://en.cppreference.com/w/cpp/utility/integer_sequence.html[`std::make_integer_sequence`]. +Likewise, `make_index_sequence` and `index_sequence_for` are analogous with +their standard counterparts. In fact each `stdx` version derives from the `std` +version, so can be used in exactly the same way, for instance: + +[source,cpp] +---- +auto sum = [](std::index_sequence) { + return (std::size_t{} + ... + Is); +}(stdx::make_index_sequence<3>{}); + +// sum is 6 +---- +The difference is that `stdx::make_integer_sequence` implements the tuple +protocol. This means that it is usable with +xref:tuple_algorithms.adoc#_tuple_algorithms_hpp[tuple algorithms]. And when +using the tuple protocol, `stdx::make_index_sequence` produces +`std::integral_constant` rather than `std::size_t{I}`. + +[source,cpp] +---- +template +auto f() { + // use make_index_sequence with tuple algorithms + stdx::unrolled_for_each( + [](auto x) { + // x is std::integral_constant for each I + }, + stdx::make_index_sequence{}); + + // or with C++26, destructure into a pack (optionally constexpr here) + auto [...Is] = stdx::make_index_sequence{}; + + // std::integral_constant implicitly converts to its contained type... + auto rt_sum = (std::size_t{} + ... + Is); + // ...or can be used at compile time + constexpr auto ct_sum = (std::size_t{} + ... + decltype(Is)::value); +} +---- + === `overload` `overload` is a struct designed to encapsulate an overload set. It inherits from diff --git a/include/stdx/span.hpp b/include/stdx/span.hpp index 87c9f18..c89b561 100644 --- a/include/stdx/span.hpp +++ b/include/stdx/span.hpp @@ -236,6 +236,12 @@ class span : public detail::span_base { } }; +template +[[nodiscard]] constexpr auto get(span s) -> decltype(s[I]) { + static_assert(E == dynamic_extent or I < E, "get() out of range on span"); + return s[I]; +} + // NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast) template auto as_bytes(span s) noexcept { if constexpr (N == dynamic_extent) { diff --git a/include/stdx/tuple.hpp b/include/stdx/tuple.hpp index dd7b792..c5d2edc 100644 --- a/include/stdx/tuple.hpp +++ b/include/stdx/tuple.hpp @@ -3,6 +3,7 @@ #if __cplusplus >= 202002L #include +#include #include #include @@ -408,6 +409,8 @@ tuple_impl(Ts...) template constexpr auto tuple_size_v = T::size(); template constexpr auto tuple_size_v> = N; +template +constexpr auto tuple_size_v> = std::size_t{N}; template using tuple_element_t = typename T::template element_t; diff --git a/include/stdx/tuple_algorithms.hpp b/include/stdx/tuple_algorithms.hpp index a1ba123..f886b18 100644 --- a/include/stdx/tuple_algorithms.hpp +++ b/include/stdx/tuple_algorithms.hpp @@ -140,7 +140,7 @@ template