Skip to content

Commit

Permalink
fix explicit template paramters in lamdba
Browse files Browse the repository at this point in the history
  • Loading branch information
poor-circle committed Jul 31, 2023
1 parent 09ed05c commit 6901a2d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 67 deletions.
37 changes: 18 additions & 19 deletions include/ylt/struct_pack/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,19 @@ using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename U>
constexpr auto get_types();

template <typename T, template <typename, typename, std::size_t> typename Op,
typename... Contexts, std::size_t... I>
constexpr void for_each_impl(std::index_sequence<I...>, Contexts &...contexts) {
using type = decltype(get_types<T>());
(Op<T, std::tuple_element_t<I, type>, I>{}(contexts...), ...);
}

template <typename T, template <typename, typename, std::size_t> typename Op,
typename... Contexts>
constexpr void for_each(Contexts &...contexts) {
using type = decltype(get_types<T>());
[&]<std::size_t... I>(std::index_sequence<I...>) {
(Op<T, std::tuple_element_t<I, type>, I>{}(contexts...), ...);
}
(std::make_index_sequence<std::tuple_size_v<type>>());
for_each_impl<T, Op>(std::make_index_sequence<std::tuple_size_v<type>>(),
contexts...);
}

template <typename T>
Expand Down Expand Up @@ -611,6 +616,12 @@ template <typename T, typename = void>
template <typename T, bool ignore_compatible_field = false>
struct is_trivial_serializable {
private:
template<typename U, std::size_t... I>
static constexpr bool class_visit_helper(std::index_sequence<I...>) {
return (is_trivial_serializable<std::tuple_element_t<I, U>,
ignore_compatible_field>::value &&
...);
}
static constexpr bool solve() {
if constexpr (is_compatible_v<T> || is_trivial_view_v<T>) {
return ignore_compatible_field;
Expand Down Expand Up @@ -648,23 +659,11 @@ template <typename T, typename = void>
ignore_compatible_field>::value;
}
else if constexpr (is_trivial_tuple<T>) {
return []<std::size_t... I>(std::index_sequence<I...>)
CONSTEXPR_INLINE_LAMBDA {
return (is_trivial_serializable<std::tuple_element_t<I, T>,
ignore_compatible_field>::value &&
...);
}
(std::make_index_sequence<std::tuple_size_v<T>>{});
return class_visit_helper<T>(std::make_index_sequence<std::tuple_size_v<T>>{});
}
else if constexpr (std::is_class_v<T>) {
using T_ = decltype(get_types<T>());
return []<std::size_t... I>(std::index_sequence<I...>)
CONSTEXPR_INLINE_LAMBDA {
return (is_trivial_serializable<std::tuple_element_t<I, T_>,
ignore_compatible_field>::value &&
...);
}
(std::make_index_sequence<std::tuple_size_v<T_>>{});
using U = decltype(get_types<T>());
return class_visit_helper<U>(std::make_index_sequence<std::tuple_size_v<U>>{});
}
else
return false;
Expand Down
113 changes: 67 additions & 46 deletions include/ylt/struct_pack/struct_pack_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,9 +257,8 @@ constexpr auto get_types() {
else if constexpr (std::is_class_v<T>) {
// clang-format off
return visit_members(
declval<T>(), []<typename... Args>(Args &&
...) constexpr {
return declval<std::tuple<remove_cvref_t<Args>...>>();
declval<T>(), [](auto &&... args) constexpr {
return declval<std::tuple<remove_cvref_t<decltype(args)>...>>();
});
// clang-format on
}
Expand Down Expand Up @@ -664,16 +663,20 @@ constexpr decltype(auto) get_size_literal() {
"The size is too large.");
}
}
template <typename arg, typename... ParentArgs>
constexpr std::size_t check_circle() {

template <typename Arg, typename... ParentArgs, std::size_t... I>
constexpr std::size_t check_circle_impl(std::index_sequence<I...>) {
using types_tuple = std::tuple<ParentArgs...>;
return (std::max)(
{(std::is_same_v<std::tuple_element_t<I, types_tuple>, Arg> ? I + 1
: 0)...});
}

template <typename Arg, typename... ParentArgs>
constexpr std::size_t check_circle() {
if constexpr (sizeof...(ParentArgs)) {
return []<std::size_t... I>(std::index_sequence<I...>) {
return (std::max)(
{(std::is_same_v<std::tuple_element_t<I, types_tuple>, arg> ? I + 1
: 0)...});
}
(std::make_index_sequence<sizeof...(ParentArgs)>());
return check_circle_impl<Arg, ParentArgs...>(
std::make_index_sequence<sizeof...(ParentArgs)>());
}
else {
return 0;
Expand Down Expand Up @@ -726,18 +729,21 @@ constexpr std::size_t alignment_impl();
template <typename T>
constexpr std::size_t alignment_v = alignment_impl<T>();

template <typename type, std::size_t... I>
constexpr std::size_t default_alignment_helper(std::index_sequence<I...>) {
return (std::max)(
{(is_compatible_v<remove_cvref_t<std::tuple_element_t<I, type>>>
? std::size_t{0}
: align::alignment_v<
remove_cvref_t<std::tuple_element_t<I, type>>>)...});
}

template <typename T>
constexpr std::size_t default_alignment() {
if constexpr (!is_trivial_serializable<T>::value && !is_trivial_view_v<T>) {
using type = decltype(get_types<T>());
return [&]<std::size_t... I>(std::index_sequence<I...>) constexpr {
return (std::max)(
{(is_compatible_v<remove_cvref_t<std::tuple_element_t<I, type>>>
? std::size_t{0}
: align::alignment_v<
remove_cvref_t<std::tuple_element_t<I, type>>>)...});
}
(std::make_index_sequence<std::tuple_size_v<type>>());
return default_alignment_helper<type>(
std::make_index_sequence<std::tuple_size_v<type>>());
}
else if constexpr (is_trivial_view_v<T>) {
return std::alignment_of_v<typename T::value_type>;
Expand All @@ -752,6 +758,15 @@ constexpr std::size_t default_alignment_v = default_alignment<T>();
template <typename T>
constexpr std::size_t alignment_impl();

template <typename type, std::size_t... I>
constexpr std::size_t pack_alignment_impl_helper(std::index_sequence<I...>) {
return (std::max)(
{(is_compatible_v<remove_cvref_t<std::tuple_element_t<I, type>>>
? std::size_t{0}
: align::alignment_v<
remove_cvref_t<std::tuple_element_t<I, type>>>)...});
}

template <typename T>
constexpr std::size_t pack_alignment_impl() {
static_assert(std::is_class_v<T>);
Expand All @@ -761,14 +776,8 @@ constexpr std::size_t pack_alignment_impl() {
ret == 16);
if constexpr (ret == 0) {
using type = decltype(get_types<T>());
return [&]<std::size_t... I>(std::index_sequence<I...>) constexpr {
return (std::max)(
{(is_compatible_v<remove_cvref_t<std::tuple_element_t<I, type>>>
? std::size_t{0}
: align::alignment_v<
remove_cvref_t<std::tuple_element_t<I, type>>>)...});
}
(std::make_index_sequence<std::tuple_size_v<type>>());
return pack_alignment_impl_helper<type>(
std::make_index_sequence<std::tuple_size_v<type>>());
}
else {
return ret;
Expand Down Expand Up @@ -1633,19 +1642,24 @@ class packer {
packer(const packer &) = delete;
packer &operator=(const packer &) = delete;

template <std::size_t size_type, typename T, std::size_t... I,
typename... Args>
void serialize_expand_compatible_helper(const T &t, std::index_sequence<I...>,
const Args &...args) {
using Type = get_args_type<T, Args...>;
(serialize_many<size_type, compatible_version_number<Type>[I]>(t, args...),
...);
}

template <uint64_t conf, std::size_t size_type, typename T, typename... Args>
STRUCT_PACK_INLINE void serialize(const T &t, const Args &...args) {
serialize_metainfo<conf, size_type == 1, T, Args...>();
serialize_many<size_type, UINT64_MAX>(t, args...);
using Type = get_args_type<T, Args...>;
if constexpr (serialize_static_config<Type>::has_compatible) {
constexpr std::size_t sz = compatible_version_number<Type>.size();
[&]<std::size_t... I>(std::index_sequence<I...>) {
(serialize_many<size_type, compatible_version_number<Type>[I]>(t,
args...),
...);
}
(std::make_index_sequence<sz>{});
return serialize_expand_compatible_helper<size_type, T, Args...>(
t, std::make_index_sequence<sz>{}, args...);
}
}

Expand Down Expand Up @@ -2512,7 +2526,7 @@ class unpacker {
}
}
else if constexpr (unique_ptr<type>) {
bool has_value;
bool has_value{};
if SP_UNLIKELY (!reader_.read((char *)&has_value, sizeof(bool))) {
return struct_pack::errc::no_buffer_space;
}
Expand Down Expand Up @@ -2679,7 +2693,7 @@ class unpacker {
item);
}
else if constexpr (optional<type> || expected<type>) {
bool has_value;
bool has_value{};
if SP_UNLIKELY (!reader_.read((char *)&has_value, sizeof(bool))) {
return struct_pack::errc::no_buffer_space;
}
Expand All @@ -2704,7 +2718,7 @@ class unpacker {
}
}
else if constexpr (is_variant_v<type>) {
uint8_t index;
uint8_t index{};
if SP_UNLIKELY (!reader_.read((char *)&index, sizeof(index))) {
return struct_pack::errc::no_buffer_space;
}
Expand Down Expand Up @@ -2774,7 +2788,7 @@ class unpacker {
}
return struct_pack::errc::no_buffer_space;
}
bool has_value;
bool has_value{};
if SP_UNLIKELY (!reader_.read((char *)&has_value, sizeof(bool))) {
return struct_pack::errc::no_buffer_space;
}
Expand Down Expand Up @@ -2907,18 +2921,25 @@ class unpacker {
return std::get<I>(std::forward_as_tuple(ts...));
}

template <size_t size_type, uint64_t version, size_t FieldIndex,
typename FieldType, typename... Args, std::size_t... I>
STRUCT_PACK_INLINE constexpr void for_each_helper(struct_pack::errc &code,
FieldType &field,
std::index_sequence<I...>,
Args &&...items) {
[[maybe_unused]] auto result =
(!set_value<size_type, version, I, FieldIndex>(code, field,
get_nth<I>(items...)) &&
...);
}

template <size_t size_type, uint64_t version, size_t FieldIndex,
typename FieldType, typename... Args>
STRUCT_PACK_INLINE constexpr decltype(auto) for_each(FieldType &field,
Args &&...items) {
STRUCT_PACK_INLINE constexpr struct_pack::errc for_each(FieldType &field,
Args &&...items) {
struct_pack::errc code{};
[&]<std::size_t... I>(std::index_sequence<I...>) CONSTEXPR_INLINE_LAMBDA {
[[maybe_unused]] auto result =
(!set_value<size_type, version, I, FieldIndex>(
code, field, get_nth<I>(items...)) &&
...);
}
(std::make_index_sequence<sizeof...(Args)>{});
for_each_helper<size_type, version, FieldIndex, FieldType>(
code, field, std::make_index_sequence<sizeof...(Args)>(), items...);
return code;
}

Expand Down
6 changes: 4 additions & 2 deletions src/struct_pack/tests/test_pragma_pack_and_alignas_mix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,14 +325,16 @@ TEST_CASE("testing mix and compatible nested") {
auto result = struct_pack::deserialize<
test_pragma_pack_and_alignas_and_compatible_mix::dummy_2_4_v2>(buffer);
CHECK(result.has_value() == true);
CHECK(result == v2);
auto val=result.value();
CHECK(val == v2);
}
{
auto buffer = struct_pack::serialize(v2);
auto result = struct_pack::deserialize<
test_pragma_pack_and_alignas_and_compatible_mix::dummy_2_4_v1>(buffer);
CHECK(result.has_value() == true);
CHECK(result == v1);
auto val=result.value();
CHECK(val == v1);
}
}

Expand Down

0 comments on commit 6901a2d

Please sign in to comment.