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
4 changes: 3 additions & 1 deletion best/base/fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct err;
template <typename...>
class row;
template <typename...>
struct row_forward;
struct args;

// best/container/pun.h
template <typename...>
Expand Down Expand Up @@ -85,6 +85,8 @@ template <auto&>
class reflected_type;

// best/meta/tlist.h
template <auto>
struct val;
template <typename...>
class tlist;

Expand Down
1 change: 1 addition & 0 deletions best/container/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ cc_test(
deps = [
":row",
"//best/test",
"//best/test:fodder",
],
)

Expand Down
1 change: 1 addition & 0 deletions best/container/internal/pun.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "best/container/object.h"
#include "best/meta/init.h"
#include "best/meta/tags.h"
#include "best/meta/tlist.h"

//! Internal implementation of best::pun.

Expand Down
105 changes: 104 additions & 1 deletion best/container/internal/row.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

#include "best/container/object.h"
#include "best/meta/empty.h"
#include "best/meta/tags.h"
#include "best/meta/internal/tlist.h"
#include "best/meta/tlist.h"

namespace best::row_internal {
Expand Down Expand Up @@ -124,6 +124,109 @@ struct impl;
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::splice_impl().
using ::best::tlist_internal::splat;
template <typename Out, size_t... i, size_t... j, size_t... k>
constexpr auto make_splicer(std::index_sequence<i...>,
std::index_sequence<j...>,
std::index_sequence<k...>, auto&&... args) {
return [&]<splat<i>... prefix, splat<j>... infix, splat<k>... suffix>(
prefix&&... pre, infix&&..., suffix&&... suf) {
return Out{BEST_FWD(pre)..., BEST_FWD(args)..., BEST_FWD(suf)...};
};
}
template <best::bounds b, typename... Ts,
auto count = b.try_compute_count(sizeof...(Ts))>
requires(count.has_value())
constexpr auto splice(auto&& row, auto those_types, auto&& those) {
using Out = decltype(row.types.template splice<b>(those_types)
.template apply<best::row>());
return BEST_FWD(row).apply([&](auto&&... args) {
return BEST_FWD(those).apply([&](auto&&... insert) {
return make_splicer<Out>(
std::make_index_sequence<b.start>{},
std::make_index_sequence<*count>{},
std::make_index_sequence<sizeof...(args) - (b.start + *count)>{},
BEST_FWD(insert)...)(BEST_FWD(args)...);
});
});
}

// See tlist_internal::gather_impl() and tlist_internal::scatter_impl().
template <size_t... i>
auto gather(auto&& row)
requires((i < best::as_auto<decltype(row)>::size()) && ...)
{
using Out =
decltype(row.types.template gather<i...>().template apply<best::row>());
return Out{BEST_FWD(row)[best::index<i>]...};
}
template <size_t... i>
auto scatter(auto&& row, auto those_types, auto&& those)
requires((i < best::as_auto<decltype(row)>::size()) && ...) &&
(sizeof...(i) <= best::as_auto<decltype(those)>::size()) &&
(sizeof...(i) <= best::as_auto<decltype(those_types)>::size()) &&
(best::as_auto<decltype(those_types)>::size() <=
best::as_auto<decltype(those)>::size())
{
using Out =
decltype(row.types
.template scatter<i...>(
those_types.template at<bounds{.count = sizeof...(i)}>())
.template apply<best::row>());
return row.indices.apply([&]<typename... J>() {
constexpr auto lut = [&] {
std::array<size_t, best::as_auto<decltype(row)>::size()> lut{
(J::value - J::value)...};
size_t n = 1;
((i < lut.size() ? lut[i] = n++ : 0), ...);
return lut;
}();
return those.apply([&](auto&&... args) {
return Out{best::row{best::bind, BEST_FWD(row)[J{}],
args...}[best::index<lut[J::value]>]...};
});
});
}

// 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)...};
constexpr auto lut = join_lut<sizeof...(i), decltype(those.types)...>;

return row<typename fast_nth<lut[i * 2], decltype(those.types)...> //
::template type<lut[i * 2 + 1]>...>{
BEST_MOVE(rowrow)[best::index<lut[i * 2]>] //
.get(best::index<lut[i * 2 + 1]>)...};
}(best::indices<(0 + ... + best::as_auto<decltype(those)>::size())>);
}
} // namespace best::row_internal

#endif // BEST_CONTAINER_INTERNAL_ROW_H_
5 changes: 2 additions & 3 deletions best/container/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class object_ptr final {
}
template <typename... Args>
BEST_INLINE_SYNTHETIC constexpr void construct_in_place(
best::row_forward<Args...> args) const
best::args<Args...> args) const
requires best::constructible<T, Args...>
{
args.row.apply(
Expand Down Expand Up @@ -333,8 +333,7 @@ class object_ptr final {
}
}
template <typename... Args>
BEST_INLINE_SYNTHETIC constexpr void assign(
best::row_forward<Args...> args) const
BEST_INLINE_SYNTHETIC constexpr void assign(best::args<Args...> args) const
requires best::constructible<T, Args...>
{
args.row.apply([&](auto&&... args) { assign(BEST_FWD(args)...); });
Expand Down
1 change: 0 additions & 1 deletion best/container/pun.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "best/container/internal/pun.h"
#include "best/container/object.h"
#include "best/meta/init.h"
#include "best/meta/tags.h"
#include "best/meta/tlist.h"

//! Untagged unions that are somewhat sensible.
Expand Down
32 changes: 16 additions & 16 deletions best/container/result.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ namespace best {
/// ```
template <typename... Args>
struct ok {
constexpr ok(Args... args) : row(BEST_FWD(args)...) {}
best::row<Args...> row;
constexpr ok(Args... args) : args(BEST_FWD(args)...) {}
best::args<Args...> args;

friend void BestFmt(auto& fmt, const ok& ok)
requires requires { fmt.format(ok.row); }
requires requires { fmt.format(ok.args); }
{
fmt.write("ok");
fmt.format(ok.row);
fmt.format(ok.args);
}
friend constexpr void BestFmtQuery(auto& query, ok*) {
query = query.template of<best::row<Args...>>;
query = query.template of<best::args<Args...>>;
}
};
template <typename... Args>
Expand All @@ -70,17 +70,17 @@ ok(Args&&...) -> ok<Args&&...>;
/// ```
template <typename... Args>
struct err {
constexpr err(Args... args) : row(BEST_FWD(args)...) {}
best::row<Args...> row;
constexpr err(Args... args) : args(BEST_FWD(args)...) {}
best::args<Args...> args;

friend void BestFmt(auto& fmt, const err& err)
requires requires { fmt.format(err.row); }
requires requires { fmt.format(err.args); }
{
fmt.write("err");
fmt.format(err.row);
fmt.format(err.args);
}
friend constexpr void BestFmtQuery(auto& query, err*) {
query = query.template of<best::row<Args...>>;
query = query.template of<best::args<Args...>>;
}
};
template <typename... Args>
Expand Down Expand Up @@ -167,15 +167,15 @@ class [[nodiscard(
template <typename... Args>
constexpr result(best::ok<Args...> args)
requires best::constructible<T, Args...>
: BEST_RESULT_IMPL_(best::index<0>, std::move(args).row.forward()) {}
: BEST_RESULT_IMPL_(best::index<0>, std::move(args).args) {}

/// # `result::result(err(...))`
///
/// Constructs an error result from a `best::error(...)`.
template <typename... Args>
constexpr result(best::err<Args...> args)
requires best::constructible<E, Args...>
: BEST_RESULT_IMPL_(best::index<1>, std::move(args).row.forward()) {}
: BEST_RESULT_IMPL_(best::index<1>, std::move(args).args) {}

/// # `result::result(result<U, F>&)`
///
Expand Down Expand Up @@ -282,11 +282,11 @@ class [[nodiscard(
}
template <best::equatable<T> U>
BEST_INLINE_SYNTHETIC constexpr bool operator==(best::ok<U> u) const {
return ok() == u.row[best::index<0>];
return ok() == u.args.row[best::index<0>];
}
template <best::equatable<E> U>
BEST_INLINE_SYNTHETIC constexpr bool operator==(best::err<U> u) const {
return err() == u.row[best::index<0>];
return err() == u.args.row[best::index<0>];
}

BEST_INLINE_SYNTHETIC constexpr bool operator==(best::ok<> u) const {
Expand All @@ -313,12 +313,12 @@ class [[nodiscard(
}
template <best::comparable<T> U>
BEST_INLINE_SYNTHETIC constexpr auto operator<=>(best::ok<U> u) const {
if (auto v = ok()) return v <=> u.row[best::index<0>];
if (auto v = ok()) return v <=> u.args.args[best::index<0>];
return best::ord::less;
}
template <best::comparable<E> U>
BEST_INLINE_SYNTHETIC constexpr auto operator<=>(best::err<U> u) const {
if (auto v = ok()) return v <=> u.rpw[best::index<0>];
if (auto v = ok()) return v <=> u.args.args[best::index<0>];
return best::ord::less;
}
BEST_INLINE_SYNTHETIC constexpr auto operator<=>(best::ok<> u) const {
Expand Down
Loading
Loading