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

Skipping and tuple cleanup #1531

Merged
merged 6 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions include/glaze/beve/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ namespace glz
static constexpr size_t count_to_write = [] {
size_t count{};
invoke_table<N>([&]<size_t I>() {
using V = std::remove_cvref_t<refl_t<T, I>>;
using V = field_t<T, I>;

if constexpr (std::same_as<V, hidden> || std::same_as<V, skip>) {
// do not serialize
Expand Down Expand Up @@ -707,7 +707,7 @@ namespace glz
}();

invoke_table<N>([&]<size_t I>() {
using val_t = std::remove_cvref_t<refl_t<T, I>>;
using val_t = field_t<T, I>;

if constexpr (std::same_as<val_t, hidden> || std::same_as<val_t, skip>) {
return;
Expand Down Expand Up @@ -745,7 +745,7 @@ namespace glz
}();

invoke_table<N>([&]<size_t I>() {
using val_t = std::remove_cvref_t<refl_t<T, I>>;
using val_t = field_t<T, I>;

if constexpr (std::same_as<val_t, hidden> || std::same_as<val_t, skip>) {
return;
Expand Down
63 changes: 25 additions & 38 deletions include/glaze/core/reflect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,53 +207,40 @@ namespace glz
static constexpr auto size = 0;
};

// The type of the field before get_member is applied
template <class T, size_t I>
using elem_t = reflect<T>::template elem<I>;

// The type of the field after get_member is applied
template <class T, size_t I>
using refl_t = reflect<T>::template type<I>;

// MSVC requires this specialization, otherwise it will try to instatiate dead `if constexpr` branches for N == 0
template <opts Opts, class T>
struct object_info;

template <opts Opts, class T>
requires(reflect<T>::size == 0)
struct object_info<Opts, T>
{
static constexpr bool maybe_skipped = false;
};


// The decayed type after get_member is called
template <class T, size_t I>
using field_t = std::remove_cvref_t<refl_t<T, I>>;

template <opts Opts, class T>
requires(reflect<T>::size > 0)
struct object_info<Opts, T>
{
static constexpr auto N = reflect<T>::size;

static constexpr bool maybe_skipped = [] {
if constexpr (N > 0 && Opts.skip_null_members) {
bool found_maybe_skipped{};
for_each_short_circuit<N>([&](auto I) {
using V = std::remove_cvref_t<refl_t<T, I>>;

if constexpr (Opts.skip_null_members && detail::null_t<V>) {
found_maybe_skipped = true;
return true; // early exit
}

if constexpr (is_includer<V> || std::same_as<V, hidden> || std::same_as<V, skip>) {
found_maybe_skipped = true;
return true; // early exit
}
return false; // continue
});
return found_maybe_skipped;
inline constexpr bool maybe_skipped = [] {
if constexpr (reflect<T>::size > 0)
{
constexpr auto N = reflect<T>::size;
if constexpr (Opts.skip_null_members) {
// if any type could be null then we might skip
return []<size_t... I>(std::index_sequence<I...>) {
return ((detail::always_skipped<field_t<T, I>> || detail::null_t<field_t<T, I>>) || ...);
}(std::make_index_sequence<N>{});
}
else {
return false;
// if we have an always_skipped type then we return true
return []<size_t... I>(std::index_sequence<I...>) {
return ((detail::always_skipped<field_t<T, I>>) || ...);
}(std::make_index_sequence<N>{});
}
}();
};
}
else {
return false;
}
}();
}

namespace glz::detail
Expand Down
8 changes: 4 additions & 4 deletions include/glaze/json/write.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1584,7 +1584,7 @@ namespace glz
constexpr auto N = reflect<T>::size;
std::optional<size_t> fixed = 2 + 16; // {} + extra padding
for_each_short_circuit<N>([&](auto I) -> bool {
using val_t = std::remove_cvref_t<refl_t<T, I>>;
using val_t = field_t<T, I>;
if constexpr (required_padding<val_t>()) {
fixed.value() += required_padding<val_t>();
fixed.value() += reflect<T>::keys[I].size() + 2; // key length
Expand Down Expand Up @@ -1677,10 +1677,10 @@ namespace glz
}();

static constexpr auto padding = round_up_to_nearest_16(maximum_key_size<T> + write_padding_bytes);
if constexpr (object_info<Opts, T>::maybe_skipped) {
if constexpr (maybe_skipped<Opts, T>) {
bool first = true;
invoke_table<N>([&]<size_t I>() {
using val_t = std::remove_cvref_t<refl_t<T, I>>;
using val_t = field_t<T, I>;

if constexpr (always_skipped<val_t>) {
return;
Expand Down Expand Up @@ -1784,7 +1784,7 @@ namespace glz
std::memcpy(&b[ix], quoted_key.data(), n);
ix += n;

using val_t = std::remove_cvref_t<refl_t<T, I>>;
using val_t = field_t<T, I>;

static constexpr auto check_opts = required_padding<val_t>() ? write_unchecked_on<Opts>() : Opts;
if constexpr (reflectable<T>) {
Expand Down
34 changes: 11 additions & 23 deletions include/glaze/tuplet/tuple.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,12 @@ namespace glz
template <class T>
using identity_t = T;

// Obtains T::type
template <class T>
using type_t = typename T::type;

template <size_t I>
using tag = std::integral_constant<size_t, I>;

template <size_t I>
constexpr tag<I> tag_v{};

template <size_t N>
using tag_range = std::make_index_sequence<N>;

Expand All @@ -51,8 +47,6 @@ namespace glz

template <class Tup>
using base_list_t = typename std::decay_t<Tup>::base_list;
template <class Tup>
using element_list_t = typename std::decay_t<Tup>::element_list;

template <class Tuple>
concept base_list_tuple = requires() { typename std::decay_t<Tuple>::base_list; };
Expand Down Expand Up @@ -140,9 +134,9 @@ namespace glz
template <class T>
using unwrap_ref_decay_t = typename std::unwrap_ref_decay<T>::type;

// tuplet::detail::get_tuple_base implementation
// tuplet::detail::apply_impl
namespace tuplet::detail
// tuplet::get_tuple_base implementation
// tuplet::apply_impl
namespace tuplet
{
template <class A, class... T>
struct get_tuple_base;
Expand Down Expand Up @@ -186,24 +180,19 @@ namespace glz
{
return {{{static_cast<type_t<Outer>&&>(tup.identity_t<Outer>::value).identity_t<Inner>::value}...}};
}
} // namespace tuplet::detail

// tuple implementation
namespace tuplet
{

template <class... T>
using tuple_base_t = typename detail::get_tuple_base<tag_range<sizeof...(T)>, T...>::type;
} // namespace tuplet
using tuple_base_t = typename get_tuple_base<tag_range<sizeof...(T)>, T...>::type;
}

template <class... T>
struct tuple : tuplet::tuple_base_t<T...>
{
static constexpr auto glaze_reflect = false;
constexpr static size_t N = sizeof...(T);
static constexpr size_t N = sizeof...(T);
using super = tuplet::tuple_base_t<T...>;
using super::operator[];
using base_list = typename super::base_list;
using element_list = tuplet::type_list<T...>;
using super::decl_elem;

template <tuplet::other_than<tuple> U> // Preserves default assignments
Expand Down Expand Up @@ -360,7 +349,6 @@ namespace glz
constexpr static size_t N = 0;
using super = tuplet::tuple_base_t<>;
using base_list = tuplet::type_list<>;
using element_list = tuplet::type_list<>;

template <tuplet::other_than<tuple> U> // Preserves default assignments
requires tuplet::stateless<U> // Check that U is similarly stateless
Expand Down Expand Up @@ -456,7 +444,7 @@ namespace glz
template <class F, tuplet::base_list_tuple Tup>
constexpr decltype(auto) apply(F&& func, Tup&& tup)
{
return tuplet::detail::apply_impl(static_cast<F&&>(func), static_cast<Tup&&>(tup),
return tuplet::apply_impl(static_cast<F&&>(func), static_cast<Tup&&>(tup),
typename std::decay_t<Tup>::base_list());
}

Expand Down Expand Up @@ -494,9 +482,9 @@ namespace glz
using big_tuple = tuple<std::decay_t<T>...>;
#endif
using outer_bases = base_list_t<big_tuple>;
constexpr auto outer = detail::get_outer_bases(outer_bases{});
constexpr auto inner = detail::get_inner_bases(outer_bases{});
return detail::cat_impl(big_tuple{{{std::forward<T>(ts)}...}}, outer, inner);
constexpr auto outer = get_outer_bases(outer_bases{});
constexpr auto inner = get_inner_bases(outer_bases{});
return cat_impl(big_tuple{{{std::forward<T>(ts)}...}}, outer, inner);
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/json_reflection_test/json_reflection_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ struct empty_t
{};

static_assert(glz::reflect<empty_t>::size == 0);
static_assert(not glz::object_info<glz::opts{}, empty_t>::maybe_skipped);
static_assert(not glz::maybe_skipped<glz::opts{}, empty_t>);

suite empty_test = [] {
"empty_t"_test = [] {
Expand Down