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

Improve alias #307

Merged
merged 6 commits into from
Sep 13, 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
13 changes: 7 additions & 6 deletions iguana/ylt/reflection/member_count.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
#endif

#include "user_reflect_macro.hpp"

namespace struct_pack {
template <typename T, uint64_t version>
struct compatible;
}
namespace ylt::reflection {
template <typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
Expand Down Expand Up @@ -47,7 +50,7 @@ constexpr bool expected = expected_impl<T>::value;

#if __cpp_concepts >= 201907L
template <typename Type>
concept optional = requires(Type optional) {
concept optional = !expected<Type> && requires(Type optional) {
optional.value();
optional.has_value();
optional.operator*();
Expand Down Expand Up @@ -87,14 +90,12 @@ template <typename T>
constexpr bool tuple_size = tuple_size_impl<T>::value;
#endif

template <typename T, uint64_t version = 0>
struct compatible;

template <typename Type>
constexpr inline bool is_compatible_v = false;

template <typename Type, uint64_t version>
constexpr inline bool is_compatible_v<compatible<Type, version>> = true;
constexpr inline bool is_compatible_v<struct_pack::compatible<Type, version>> =
true;

struct UniversalVectorType {
template <typename T>
Expand Down
82 changes: 48 additions & 34 deletions iguana/ylt/reflection/member_names.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

namespace ylt::reflection {

template <typename T>
struct ylt_alias_struct;

template <typename T>
inline constexpr auto get_alias_field_names();

Expand Down Expand Up @@ -64,32 +61,54 @@ struct member_tratis<T Owner::*> {
};

template <typename T, typename = void>
struct has_alias_field_names_t : std::false_type {};
struct has_alias_struct_name_t : std::false_type {};

template <typename T>
struct has_alias_field_names_t<
T, std::void_t<decltype(ylt_alias_struct<T>::get_alias_field_names())>>
struct has_alias_struct_name_t<
T, std::void_t<decltype(get_alias_struct_name((T*)nullptr))>>
: std::true_type {};

template <typename T, typename = void>
struct has_inner_alias_struct_name_t : std::false_type {};

template <typename T>
struct has_inner_alias_struct_name_t<
T, std::void_t<decltype(T::get_alias_struct_name((T*)nullptr))>>
: std::true_type {};

template <typename T>
inline constexpr bool has_alias_field_names_v =
has_alias_field_names_t<T>::value;
constexpr bool has_alias_struct_name_v = has_alias_struct_name_t<T>::value;

template <typename T>
constexpr bool has_inner_alias_struct_name_v =
has_inner_alias_struct_name_t<T>::value;

template <typename T, typename = void>
struct has_alias_struct_names_t : std::false_type {};
struct has_alias_field_names_t : std::false_type {};

template <typename T>
struct has_alias_struct_names_t<
T, std::void_t<decltype(ylt_alias_struct<T>::get_alias_struct_name())>>
struct has_alias_field_names_t<
T, std::void_t<decltype(get_alias_field_names((T*)nullptr))>>
: std::true_type {};

template <typename T, typename = void>
struct has_inner_alias_field_names_t : std::false_type {};

template <typename T>
struct has_inner_alias_field_names_t<
T, std::void_t<decltype(T::get_alias_field_names((T*)nullptr))>>
: std::true_type {};

template <typename T>
inline constexpr bool has_alias_struct_name_v =
has_alias_struct_names_t<T>::value;
constexpr bool has_alias_field_names_v = has_alias_field_names_t<T>::value;

template <typename T>
constexpr bool has_inner_alias_field_names_v =
has_inner_alias_field_names_t<T>::value;

template <typename T, typename U, size_t... Is>
inline constexpr void init_arr_with_tuple(const T& tp, U& arr,
std::index_sequence<Is...>) {
inline constexpr void init_arr_with_tuple(U& arr, std::index_sequence<Is...>) {
constexpr auto tp = struct_to_tuple<T>();
((arr[Is] = internal::get_member_name<internal::wrap(std::get<Is>(tp))>()),
...);
}
Expand All @@ -106,18 +125,17 @@ get_member_names() {
return type::refl_member_names(ylt::reflection::identity<type>{});
}
else {
constexpr auto tp = struct_to_tuple<T>();

std::array<std::string_view, Count> arr;
#if __cplusplus >= 202002L
constexpr auto tp = struct_to_tuple<T>();
[&]<size_t... Is>(std::index_sequence<Is...>) mutable {
((arr[Is] =
internal::get_member_name<internal::wrap(std::get<Is>(tp))>()),
...);
}
(std::make_index_sequence<Count>{});
#else
init_arr_with_tuple(tp, arr, std::make_index_sequence<Count>{});
init_arr_with_tuple<T>(arr, std::make_index_sequence<Count>{});
#endif
return arr;
}
Expand Down Expand Up @@ -210,26 +228,18 @@ inline constexpr size_t index_of() {
return names.size();
}

template <size_t Idx>
struct field_alias_t {
std::string_view alias_name;
inline static constexpr auto index = Idx;
size_t index;
};

template <typename Tuple, size_t... Is>
inline constexpr auto get_alias_field_names_impl(Tuple& tp,
std::index_sequence<Is...>) {
return std::array<std::pair<size_t, std::string_view>, sizeof...(Is)>{
std::make_pair(std::tuple_element_t<Is, std::decay_t<Tuple>>::index,
std::get<Is>(tp).alias_name)...};
}

template <typename T>
inline constexpr auto get_alias_field_names() {
if constexpr (internal::has_alias_field_names_v<T>) {
constexpr auto tp = ylt_alias_struct<T>::get_alias_field_names();
return get_alias_field_names_impl(
tp, std::make_index_sequence<std::tuple_size_v<decltype(tp)>>{});
return get_alias_field_names((T*)nullptr);
}
else if constexpr (internal::has_inner_alias_field_names_v<T>) {
return T::get_alias_field_names((T*)nullptr);
}
else {
return std::array<std::string_view, 0>{};
Expand All @@ -239,7 +249,10 @@ inline constexpr auto get_alias_field_names() {
template <typename T>
constexpr std::string_view get_struct_name() {
if constexpr (internal::has_alias_struct_name_v<T>) {
return ylt_alias_struct<T>::get_alias_struct_name();
return get_alias_struct_name((T*)nullptr);
}
else if constexpr (internal::has_inner_alias_struct_name_v<T>) {
return T::get_alias_struct_name((T*)nullptr);
}
else {
return type_string<T>();
Expand All @@ -251,10 +264,11 @@ inline constexpr std::array<std::string_view, members_count_v<T>>
get_member_names() {
auto arr = internal::get_member_names<T>();
using U = ylt::reflection::remove_cvref_t<T>;
if constexpr (internal::has_alias_field_names_v<U>) {
if constexpr (internal::has_alias_field_names_v<U> ||
internal::has_inner_alias_field_names_v<U>) {
constexpr auto alias_arr = get_alias_field_names<U>();
for (size_t i = 0; i < alias_arr.size(); i++) {
arr[alias_arr[i].first] = alias_arr[i].second;
arr[alias_arr[i].index] = alias_arr[i].alias_name;
}
}
return arr;
Expand Down
2 changes: 1 addition & 1 deletion iguana/ylt/reflection/member_ptr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

// modified based on:
// https://github.com/getml/reflect-cpp/blob/main/include/rfl/internal/bind_fake_object_to_tuple.hpp
// thanks for alxn4's greate idea!
// thanks for alxn4's great idea!
namespace ylt::reflection {
namespace internal {

Expand Down
19 changes: 9 additions & 10 deletions test/test_cpp20.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ YLT_REFL(point_t, x, y);
struct point_t1 {
int x;
int y;
};
YLT_REFL(point_t1, x, y);

template <>
struct ylt::reflection::ylt_alias_struct<point_t1> {
static constexpr std::string_view get_alias_struct_name() { return "point"; }

static constexpr auto get_alias_field_names() {
return std::make_tuple(field_alias_t<0>{"X"}, field_alias_t<1>{"Y"});
static constexpr auto get_alias_field_names(point_t1*) {
return std::array{field_alias_t{"X", 0}, field_alias_t{"Y", 1}};
}
static constexpr std::string_view get_alias_struct_name(point_t1*) {
return "point";
}
};
YLT_REFL(point_t1, x, y);

struct test_variant {
test_variant() = default;
test_variant(int a, std::variant<double, std::string, int> b, double c)
Expand Down Expand Up @@ -253,8 +252,8 @@ TEST_CASE("test xml") {
constexpr auto names = ylt::reflection::get_member_names<point_t1>();
constexpr auto st_name = ylt::reflection::get_struct_name<point_t1>();
CHECK(names == std::array<std::string_view, 2>{"X", "Y"});
CHECK(alias_names[0].second == "X");
CHECK(alias_names[1].second == "Y");
CHECK(alias_names[0].alias_name == "X");
CHECK(alias_names[1].alias_name == "Y");
CHECK(st_name == "point");

constexpr auto name1 = ylt::reflection::get_struct_name<int>();
Expand Down
28 changes: 14 additions & 14 deletions test/test_xml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,14 +734,14 @@ struct next_obj_t {
};
YLT_REFL(next_obj_t, x, y);

template <>
struct ylt::reflection::ylt_alias_struct<next_obj_t> {
static constexpr std::string_view get_alias_struct_name() { return "next"; }
inline constexpr std::string_view get_alias_struct_name(next_obj_t *) {
return "next";
}

static constexpr auto get_alias_field_names() {
return std::make_tuple(field_alias_t<0>{"w"}, field_alias_t<1>{"h"});
}
};
inline constexpr auto get_alias_field_names(next_obj_t *) {
return std::array{ylt::reflection::field_alias_t{"w", 0},
ylt::reflection::field_alias_t{"h", 1}};
}

struct out_object {
std::unique_ptr<int> id;
Expand All @@ -750,14 +750,14 @@ struct out_object {
YLT_REFL(out_object, id, name, obj);
};

template <>
struct ylt::reflection::ylt_alias_struct<out_object> {
static constexpr std::string_view get_alias_struct_name() { return "qi"; }
inline constexpr std::string_view get_alias_struct_name(out_object *) {
return "qi";
}

static constexpr auto get_alias_field_names() {
return std::make_tuple(field_alias_t<0>{"w"}, field_alias_t<1>{"h"});
}
};
inline constexpr auto get_alias_field_names(out_object *) {
return std::array{ylt::reflection::field_alias_t{"w", 0},
ylt::reflection::field_alias_t{"h", 1}};
}

TEST_CASE("test alias") {
out_object m{std::make_unique<int>(20), "tom", {21, 42}};
Expand Down
Loading