Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All the row operations: best::{tlist, row}::{at, join, push, insert, splice, remove, erase, gather, scatter} #12

Merged
merged 12 commits into from
Jun 24, 2024
Prev Previous commit
Next Next commit
add row::at(range)
  • Loading branch information
mcy committed Jun 24, 2024
commit dd871ef664c36effbb2a0f92ddfcb5ce1de98d01
25 changes: 24 additions & 1 deletion best/container/internal/row.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,32 @@ template <size_t... i, typename... Elems>
struct impl<const best::vlist<i...>, Elems...>
: best::ebo<best::object<Elems>, Elems, i>... {};

// See tlist_internal::slice_impl().
using ::best::tlist_internal::splat;
template <typename Out, size_t... i, size_t... j, size_t... k>
constexpr auto make_slicer(std::index_sequence<i...>, std::index_sequence<j...>,
std::index_sequence<k...>) {
return []<splat<i>... prefix, splat<j>... infix, splat<k>... suffix>(
prefix&&..., infix&&... args, suffix&&...) {
return Out{BEST_FWD(args)...};
};
}
template <best::bounds b, typename... Ts,
auto count = b.try_compute_count(sizeof...(Ts))>
requires(count.has_value())
constexpr auto slice(auto&& row) {
using Out = decltype(row.types.template at<b>().template apply<best::row>());
return BEST_FWD(row).apply([](auto&&... args) {
return make_slicer<Out>(
std::make_index_sequence<b.start>{}, std::make_index_sequence<*count>{},
std::make_index_sequence<sizeof...(args) - (b.start + *count)>{})(
BEST_FWD(args)...);
});
}

// See tlist_internal::join().
using ::best::tlist_internal::fast_nth;
using ::best::tlist_internal::join_lut;

constexpr auto join(auto&&... those) {
return [&]<auto... i>(best::vlist<i...>) {
auto rowrow = best::row{best::bind, BEST_FWD(those)...};
Expand Down
97 changes: 73 additions & 24 deletions best/container/row.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,24 +177,33 @@ class row final
/// Returns whether this is the empty row `best::row<>`.
constexpr static bool is_empty() { return types.size() == 0; }

/// # `row[index<n>]`
/// # `row[index<n>]`, `row[best::values<bounds{...}>]`
///
/// Returns the `n`th element.
/// Returns a reference to the `n`th element, or a subrange as a row (values
/// are copied/moved as appropriate).
// clang-format off
template <size_t n> constexpr cref<n> operator[](best::index_t<n> idx) const&;
template <size_t n> constexpr ref<n> operator[](best::index_t<n> idx) &;
template <size_t n> constexpr crref<n> operator[](best::index_t<n> idx) const&&;
template <size_t n> constexpr rref<n> operator[](best::index_t<n> idx) &&;
template <size_t n> constexpr cref<n> operator[](best::index_t<n>) const&;
template <size_t n> constexpr ref<n> operator[](best::index_t<n>) &;
template <size_t n> constexpr crref<n> operator[](best::index_t<n>) const&&;
template <size_t n> constexpr rref<n> operator[](best::index_t<n>) &&;
template <best::bounds range> constexpr auto operator[](best::vlist<range>) const&;
template <best::bounds range> constexpr auto operator[](best::vlist<range>) &;
template <best::bounds range> constexpr auto operator[](best::vlist<range>) const&&;
template <best::bounds range> constexpr auto operator[](best::vlist<range>) &&;
// clang-format on

/// # `row::at(index<n>)`
/// # `row::at(index<n>)`, `row::at(best::values<bounds{...}>)`
///
/// Identical to `operator[]` in all ways.
// clang-format off
template <size_t n> constexpr cref<n> at(best::index_t<n> = {}) const&;
template <size_t n> constexpr ref<n> at(best::index_t<n> = {}) &;
template <size_t n> constexpr crref<n> at(best::index_t<n> = {}) const&&;
template <size_t n> constexpr rref<n> at(best::index_t<n> = {}) &&;
template <best::bounds range> constexpr auto at(best::vlist<range> = {}) const&;
template <best::bounds range> constexpr auto at(best::vlist<range> = {}) &;
template <best::bounds range> constexpr auto at(best::vlist<range> = {}) const&&;
template <best::bounds range> constexpr auto at(best::vlist<range> = {}) &&;
// clang-format on

/// # `row::object(index<n>)`
Expand Down Expand Up @@ -232,22 +241,6 @@ class row final
template <typename T> constexpr decltype(auto) select(best::tlist<T> idx = {}) &&;
// clang-format on

/// # `tlist::join()`, `tlist::operator+`
///
/// Concatenates several rows with this one.
///
/// This is also made available via `operator+`, but beware: using a fold with
/// `operator+` here is quadratic; you should generally prefer `join()` for
/// variadic cases.
constexpr auto join(best::is_row auto&&...) const&;
constexpr auto join(best::is_row auto&&...) &;
constexpr auto join(best::is_row auto&&...) const&&;
constexpr auto join(best::is_row auto&&...) &&;
constexpr auto operator+(best::is_row auto&&) const&;
constexpr auto operator+(best::is_row auto&&) &;
constexpr auto operator+(best::is_row auto&&) const&&;
constexpr auto operator+(best::is_row auto&&) &&;

/// # `row::first()`, `row::second()`, `row::last()`
///
/// Gets the first, second, or last value; helper for `std::pair`-like uses.
Expand All @@ -266,6 +259,22 @@ class row final
constexpr decltype(auto) last() && requires (!types.is_empty());
// clang-format on

/// # `tlist::join()`, `tlist::operator+`
///
/// Concatenates several rows with this one.
///
/// This is also made available via `operator+`, but beware: using a fold with
/// `operator+` here is quadratic; you should generally prefer `join()` for
/// variadic cases.
constexpr auto join(best::is_row auto&&...) const&;
constexpr auto join(best::is_row auto&&...) &;
constexpr auto join(best::is_row auto&&...) const&&;
constexpr auto join(best::is_row auto&&...) &&;
constexpr auto operator+(best::is_row auto&&) const&;
constexpr auto operator+(best::is_row auto&&) &;
constexpr auto operator+(best::is_row auto&&) const&&;
constexpr auto operator+(best::is_row auto&&) &&;

/// # `row::apply()`
///
/// Calls `f` with a pack of references of the elements of this tuple.
Expand Down Expand Up @@ -418,6 +427,27 @@ constexpr row<A...>::rref<n> row<A...>::operator[](best::index_t<n> idx) && {
return static_cast<best::as_rref<T>>(*static_cast<B&>(*this).get());
}

template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::operator[](best::vlist<range>) const& {
return row_internal::slice<range, A...>(*this);
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::operator[](best::vlist<range>) & {
return row_internal::slice<range, A...>(*this);
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::operator[](best::vlist<range>) const&& {
return row_internal::slice<range, A...>(BEST_MOVE(*this));
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::operator[](best::vlist<range>) && {
return row_internal::slice<range, A...>(BEST_MOVE(*this));
}

template <typename... A>
template <size_t n>
constexpr row<A...>::cref<n> row<A...>::at(best::index_t<n> idx) const& {
Expand Down Expand Up @@ -447,7 +477,26 @@ constexpr row<A...>::rref<n> row<A...>::at(best::index_t<n> idx) && {
using B = best::ebo<best::object<T>, T, n>;
return static_cast<best::as_rref<T>>(*static_cast<B&>(*this).get());
}

template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::at(best::vlist<range>) const& {
return row_internal::slice<range, A...>(*this);
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::at(best::vlist<range>) & {
return row_internal::slice<range, A...>(*this);
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::at(best::vlist<range>) const&& {
return row_internal::slice<range, A...>(BEST_MOVE(*this));
}
template <typename... A>
template <best::bounds range>
constexpr auto row<A...>::at(best::vlist<range>) && {
return row_internal::slice<range, A...>(BEST_MOVE(*this));
}
template <typename... A>
template <size_t n>
constexpr const best::object<typename row<A...>::template type<n>>&
Expand Down
10 changes: 10 additions & 0 deletions best/container/row_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,14 @@ best::test Join = [](auto& t) {
best::row<MoveOnly> x2 = BEST_MOVE(x1) + best::row();
x2 = best::row() + BEST_MOVE(x1);
};

best::test Slice = [](auto& t) {
best::row<int, long, int*, int> x0{1, 2, nullptr, 4};
t.expect_eq(x0.at<bounds{.count = 2}>(), best::row{1, 2});
t.expect_eq(x0.at<bounds{.start = 2}>(), best::row{nullptr, 4});
t.expect_eq(x0.at<bounds{.start = 2, .count = 0}>(), best::row{});

best::row x1{MoveOnly(), 42};
BEST_MOVE(x1).at<bounds{.start = 0, .count = 1}>();
};
} // namespace best::row_test