Skip to content

Commit

Permalink
inner reflection (#398)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Aug 3, 2023
1 parent 8d4e1a2 commit 5f8776a
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 26 deletions.
2 changes: 1 addition & 1 deletion include/ylt/thirdparty/iguana/json_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ IGUANA_INLINE void to_json(T &&t, Stream &s) {
s.push_back('{');
for_each(std::forward<T>(t),
[&t, &s](const auto &v, auto i) IGUANA__INLINE_LAMBDA {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
constexpr auto Idx = decltype(i)::value;
constexpr auto Count = M::value();
static_assert(Idx < Count);
Expand Down
83 changes: 61 additions & 22 deletions include/ylt/thirdparty/iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,8 @@ namespace iguana::detail {
MACRO_CONCAT(CON_STR, GET_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)

#define MAKE_META_DATA_IMPL(STRUCT_NAME, ...) \
inline auto iguana_reflect_members(STRUCT_NAME const &) { \
[[maybe_unused]] inline static auto iguana_reflect_members( \
STRUCT_NAME const &) { \
struct reflect_members { \
constexpr decltype(auto) static apply_impl() { \
return std::make_tuple(__VA_ARGS__); \
Expand All @@ -574,13 +575,13 @@ namespace iguana::detail {
return reflect_members{}; \
}

#define MAKE_META_DATA(STRUCT_NAME, TABLE_NAME, N, ...) \
constexpr inline std::array<frozen::string, N> arr_##STRUCT_NAME = { \
MARCO_EXPAND(MACRO_CONCAT(CON_STR, N)(__VA_ARGS__))}; \
constexpr inline std::string_view fields_##STRUCT_NAME = { \
MAKE_NAMES(__VA_ARGS__)}; \
constexpr inline std::string_view name_##STRUCT_NAME = TABLE_NAME; \
MAKE_META_DATA_IMPL(STRUCT_NAME, \
#define MAKE_META_DATA(STRUCT_NAME, TABLE_NAME, N, ...) \
static constexpr inline std::array<frozen::string, N> arr_##STRUCT_NAME = { \
MARCO_EXPAND(MACRO_CONCAT(CON_STR, N)(__VA_ARGS__))}; \
static constexpr inline std::string_view fields_##STRUCT_NAME = { \
MAKE_NAMES(__VA_ARGS__)}; \
static constexpr inline std::string_view name_##STRUCT_NAME = TABLE_NAME; \
MAKE_META_DATA_IMPL(STRUCT_NAME, \
MAKE_ARG_LIST(N, &STRUCT_NAME::FIELD, __VA_ARGS__))

#define MAKE_META_DATA_IMPL_EMPTY(STRUCT_NAME) \
Expand Down Expand Up @@ -634,13 +635,16 @@ namespace iguana {
MAKE_META_DATA(STRUCT_NAME, TABLE_NAME, GET_ARG_COUNT(__VA_ARGS__), \
__VA_ARGS__)

template <typename T>
inline auto iguana_reflect_type(const T &t);

inline std::unordered_map<
std::string_view,
std::vector<std::pair<std::string_view, std::string_view>>>
g_iguana_custom_map;
template <typename T>
inline constexpr auto get_iguana_struct_map() {
using reflect_members = decltype(iguana_reflect_members(std::declval<T>()));
using reflect_members = decltype(iguana_reflect_type(std::declval<T>()));
if constexpr (reflect_members::value() == 0) {
return std::array<int, 0>{};
}
Expand Down Expand Up @@ -732,13 +736,49 @@ inline int add_custom_fields(std::string_view key,
template <typename T>
using Reflect_members = decltype(iguana_reflect_members(std::declval<T>()));

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

template <typename T>
struct is_public_reflection<
T, std::void_t<decltype(iguana_reflect_members(std::declval<T>()))>>
: std::true_type {};

template <typename T>
constexpr bool is_public_reflection_v = is_public_reflection<T>::value;

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

template <typename T>
struct is_private_reflection<
T, std::void_t<decltype(std::declval<T>().iguana_reflect_members(
std::declval<T>()))>> : std::true_type {};

template <typename T>
constexpr bool is_private_reflection_v = is_private_reflection<T>::value;

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

template <typename T>
struct is_reflection<T, std::void_t<decltype(Reflect_members<T>::arr())>>
struct is_reflection<T, std::enable_if_t<is_private_reflection_v<T>>>
: std::true_type {};

template <typename T>
struct is_reflection<T, std::enable_if_t<is_public_reflection_v<T>>>
: std::true_type {};

template <typename T>
inline auto iguana_reflect_type(const T &t) {
if constexpr (is_public_reflection_v<T>) {
return iguana_reflect_members(t);
}
else {
return t.iguana_reflect_members(t);
}
}

template <typename T>
inline constexpr bool is_reflection_v = is_reflection<T>::value;

Expand All @@ -761,14 +801,14 @@ constexpr int element_index_helper() {

template <template <typename...> typename Condition, typename T>
constexpr int tuple_element_index() {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
using Tuple = decltype(M::apply_impl());
return element_index_helper<0, Condition, Tuple, T>();
}

template <size_t I, typename T>
constexpr decltype(auto) get(T &&t) {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
using U = decltype(std::forward<T>(t).*(std::get<I>(M::apply_impl())));

if constexpr (std::is_array_v<U>) {
Expand Down Expand Up @@ -798,33 +838,33 @@ constexpr auto get_impl(T &t, std::index_sequence<Is...>) {

template <typename T>
constexpr auto get(T const &t) {
using M = decltype(iguana_reflect_members(t));
using M = decltype(iguana_reflect_type(t));
return get_impl(t, std::make_index_sequence<M::value()>{});
}

template <typename T>
constexpr auto get_ref(T &t) {
using M = decltype(iguana_reflect_members(t));
using M = decltype(iguana_reflect_type(t));
return get_impl(t, std::make_index_sequence<M::value()>{});
}

template <typename T, size_t I>
constexpr const auto get_name() {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
static_assert(I < M::value(), "out of range");
return M::arr()[I];
}

template <typename T>
constexpr const auto get_name(size_t i) {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
// static_assert(I<M::value(), "out of range");
return M::arr()[i];
}

template <typename T>
constexpr const std::string_view get_name() {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
return M::name();
}

Expand All @@ -836,7 +876,7 @@ constexpr const std::string_view get_fields() {

template <typename T>
constexpr std::enable_if_t<is_reflection<T>::value, size_t> get_value() {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
return M::value();
}

Expand All @@ -847,7 +887,7 @@ constexpr std::enable_if_t<!is_reflection<T>::value, size_t> get_value() {

template <typename T>
constexpr auto get_array() {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
return M::arr();
}

Expand Down Expand Up @@ -882,7 +922,7 @@ inline std::string_view get_custom_fields(std::string_view origin) {

template <typename T>
constexpr auto get_index(std::string_view name) {
using M = decltype(iguana_reflect_members(std::declval<T>()));
using M = decltype(iguana_reflect_type(std::declval<T>()));
constexpr auto arr = M::arr();

auto it = std::find_if(arr.begin(), arr.end(), [name](auto str) {
Expand Down Expand Up @@ -917,15 +957,14 @@ constexpr void for_each(const std::tuple<Args...> &t, F &&f,

template <typename T, typename F>
constexpr std::enable_if_t<is_reflection<T>::value> for_each(T &&t, F &&f) {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
for_each(M::apply_impl(), std::forward<F>(f),
std::make_index_sequence<M::value()>{});
}

template <typename T, typename F>
constexpr std::enable_if_t<is_tuple<std::decay_t<T>>::value> for_each(T &&t,
F &&f) {
// using M = decltype(iguana_reflect_members(std::forward<T>(t)));
constexpr const size_t SIZE = std::tuple_size_v<std::decay_t<T>>;
for_each(std::forward<T>(t), std::forward<F>(f),
std::make_index_sequence<SIZE>{});
Expand Down
2 changes: 1 addition & 1 deletion include/ylt/thirdparty/iguana/xml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ IGUANA_INLINE void render_xml_value(Stream &ss, T &&t, std::string_view name) {
}
for_each(std::forward<T>(t),
[&](const auto &v, auto i) IGUANA__INLINE_LAMBDA {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
using value_type = std::remove_cvref_t<decltype(t.*v)>;
constexpr auto Idx = decltype(i)::value;
constexpr auto Count = M::value();
Expand Down
2 changes: 1 addition & 1 deletion include/ylt/thirdparty/iguana/yaml_writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ template <typename Stream, typename T, std::enable_if_t<refletable_v<T>, int>>
IGUANA_INLINE void to_yaml(T &&t, Stream &s, size_t min_spaces) {
for_each(std::forward<T>(t),
[&t, &s, min_spaces](const auto &v, auto i) IGUANA__INLINE_LAMBDA {
using M = decltype(iguana_reflect_members(std::forward<T>(t)));
using M = decltype(iguana_reflect_type(std::forward<T>(t)));
constexpr auto Idx = decltype(i)::value;
constexpr auto Count = M::value();
static_assert(Idx < Count);
Expand Down
26 changes: 26 additions & 0 deletions src/struct_json/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ bool operator==(const person& a, const person& b) {

REFLECTION(person, name, age);

class some_object {
int id;
std::string name;

public:
some_object() = default;
some_object(int i, std::string str) : id(i), name(str) {}
int get_id() const { return id; }
std::string get_name() const { return name; }
REFLECTION(some_object, id, name);
};

void test_inner_object() {
some_object obj{20, "tom"};
std::string str;
iguana::to_json(obj, str);
std::cout << str << "\n";

some_object obj1;
iguana::from_json(obj1, str);
assert(obj1.get_id() == 20);
assert(obj1.get_name() == "tom");
}

int main() {
person p{"tom", 20};
std::string str;
Expand All @@ -33,4 +57,6 @@ int main() {
struct_json::parse(val, str);
assert(val.at<std::string>("name") == "tom");
assert(val.at<int>("age") == 20);

test_inner_object();
}
25 changes: 25 additions & 0 deletions src/struct_xml/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,36 @@ void required_field() {
}
}

class some_object {
int id;
std::string name;

public:
some_object() = default;
some_object(int i, std::string str) : id(i), name(str) {}
int get_id() const { return id; }
std::string get_name() const { return name; }
REFLECTION(some_object, id, name);
};

void test_inner_object() {
some_object obj{20, "tom"};
std::string str;
iguana::to_xml(obj, str);
std::cout << str << "\n";

some_object obj1;
iguana::from_xml(obj1, str);
assert(obj1.get_id() == 20);
assert(obj1.get_name() == "tom");
}

int main() {
basic_usage();
type_to_string();
nested_xml();
attribute();
get_error();
required_field();
test_inner_object();
}
29 changes: 28 additions & 1 deletion src/struct_yaml/examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,31 @@ age: 30
iguana::from_yaml(p2, ss);
}

int main() { person_example(); }
class some_object {
int id;
std::string name;

public:
some_object() = default;
some_object(int i, std::string str) : id(i), name(str) {}
int get_id() const { return id; }
std::string get_name() const { return name; }
REFLECTION(some_object, id, name);
};

void test_inner_object() {
some_object obj{20, "tom"};
std::string str;
iguana::to_yaml(obj, str);
std::cout << str << "\n";

some_object obj1;
iguana::from_yaml(obj1, str);
assert(obj1.get_id() == 20);
assert(obj1.get_name() == "tom");
}

int main() {
person_example();
test_inner_object();
}

0 comments on commit 5f8776a

Please sign in to comment.