Skip to content

Commit

Permalink
Merge pull request #307 from qicosmos/improve_alias
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Sep 13, 2024
2 parents 570d1b9 + dc98586 commit 90dff0f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 65 deletions.
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

0 comments on commit 90dff0f

Please sign in to comment.