Skip to content

Commit

Permalink
[reflection][feat]Improve reflection (#718)
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Jul 16, 2024
1 parent d1fc7fa commit b8fe6be
Show file tree
Hide file tree
Showing 12 changed files with 3,565 additions and 7,715 deletions.
53 changes: 43 additions & 10 deletions include/ylt/reflection/member_count.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,39 @@
#include <tuple>
#include <type_traits>
#include <vector>
#include <ylt/util/expected.hpp>

namespace ylt::reflection {
namespace internal {
template <typename T>
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;

#if __cpp_concepts >= 201907L
template <typename Type>
concept tuple_size = requires(Type tuple) {
std::tuple_size<std::remove_cvref_t<Type>>::value;
concept expected = requires(Type e) {
typename remove_cvref_t<Type>::value_type;
typename remove_cvref_t<Type>::error_type;
typename remove_cvref_t<Type>::unexpected_type;
e.has_value();
e.error();
requires std::is_same_v<void, typename remove_cvref_t<Type>::value_type> ||
requires(Type e) {
e.value();
};
};
#else
template <typename T, typename = void>
struct tuple_size_impl : std::false_type {};
struct expected_impl : std::false_type {};

template <typename T>
struct tuple_size_impl<
T, std::void_t<decltype(std::tuple_size<remove_cvref_t<T>>::value)>>
struct expected_impl<T, std::void_t<typename remove_cvref_t<T>::value_type,
typename remove_cvref_t<T>::error_type,
typename remove_cvref_t<T>::unexpected_type,
decltype(std::declval<T>().has_value()),
decltype(std::declval<T>().error())>>
: std::true_type {};

// TODO: check e.value()
template <typename T>
constexpr bool tuple_size = tuple_size_impl<T>::value;
constexpr bool expected = expected_impl<T>::value;
#endif

#if __cpp_concepts >= 201907L
Expand All @@ -31,7 +45,7 @@ concept optional = requires(Type optional) {
optional.value();
optional.has_value();
optional.operator*();
typename std::remove_cvref_t<Type>::value_type;
typename remove_cvref_t<Type>::value_type;
};
#else
template <typename T, typename = void>
Expand All @@ -48,6 +62,25 @@ template <typename T>
constexpr bool optional = !expected<T> && optional_impl<T>::value;
#endif

namespace internal {
#if __cpp_concepts >= 201907L
template <typename Type>
concept tuple_size = requires(Type tuple) {
std::tuple_size<remove_cvref_t<Type>>::value;
};
#else
template <typename T, typename = void>
struct tuple_size_impl : std::false_type {};

template <typename T>
struct tuple_size_impl<
T, std::void_t<decltype(std::tuple_size<remove_cvref_t<T>>::value)>>
: std::true_type {};

template <typename T>
constexpr bool tuple_size = tuple_size_impl<T>::value;
#endif

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

Expand Down Expand Up @@ -127,7 +160,7 @@ inline constexpr std::size_t members_count_impl() {

template <typename T>
inline constexpr std::size_t members_count() {
using type = std::remove_cvref_t<T>;
using type = remove_cvref_t<T>;
if constexpr (internal::tuple_size<type>) {
return std::tuple_size<type>::value;
}
Expand Down
2,754 changes: 2,754 additions & 0 deletions include/ylt/reflection/member_macro.hpp

Large diffs are not rendered by default.

53 changes: 31 additions & 22 deletions include/ylt/reflection/member_names.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include <variant>

#include "template_string.hpp"
#if __has_include(<concepts>) || defined(__clang__) || defined(_MSC_VER) || \
#if (__has_include(<concepts>) || defined(__clang__) || defined(_MSC_VER)) || \
(defined(__GNUC__) && __GNUC__ > 10)
#include "member_ptr.hpp"

Expand Down Expand Up @@ -49,7 +49,6 @@ inline constexpr std::string_view get_member_name() {
"or MSVC or switch to the rfl::Field-syntax.");
#endif
}
} // namespace internal

template <typename T>
inline constexpr std::array<std::string_view, members_count_v<T>>
Expand All @@ -66,14 +65,15 @@ get_member_names() {
return arr;
}

template <typename... Args>
inline constexpr auto tuple_to_variant(std::tuple<Args...>) {
return std::variant<std::add_pointer_t<Args>...>{};
}

template <typename T>
using struct_variant_t = decltype(tuple_to_variant(
std::declval<decltype(struct_to_tuple<std::remove_cvref_t<T>>())>));
inline constexpr auto get_member_names_map() {
constexpr auto name_arr = get_member_names<T>();
return [&]<size_t... Is>(std::index_sequence<Is...>) mutable {
return frozen::unordered_map<frozen::string, size_t, name_arr.size()>{
{name_arr[Is], Is}...};
}
(std::make_index_sequence<name_arr.size()>{});
}

template <typename T>
inline const auto& get_member_offset_arr() {
Expand All @@ -88,20 +88,29 @@ inline const auto& get_member_offset_arr() {
return arr;
}
(std::make_index_sequence<Count>{})
}; // namespace ylt::reflection
}; // namespace internal

return arr;
} // namespace ylt::reflection
} // namespace internal

template <typename... Args>
inline constexpr auto tuple_to_variant(std::tuple<Args...>) {
return std::variant<std::add_pointer_t<Args>...>{};
}

template <typename T>
inline constexpr auto get_member_names_map() {
constexpr auto name_arr = get_member_names<T>();
return [&]<size_t... Is>(std::index_sequence<Is...>) mutable {
return frozen::unordered_map<frozen::string, size_t, name_arr.size()>{
{name_arr[Is], Is}...};
}
(std::make_index_sequence<name_arr.size()>{});
}
using struct_variant_t = decltype(tuple_to_variant(
std::declval<decltype(struct_to_tuple<std::remove_cvref_t<T>>())>));

template <typename T>
constexpr auto member_names_map = internal::get_member_names_map<T>();

template <typename T>
constexpr auto member_names = internal::get_member_names<T>();

template <typename T>
inline auto member_offsets = internal::get_member_offset_arr<T>();

template <std::size_t N>
struct FixedString {
Expand All @@ -118,7 +127,7 @@ struct FixedString {

template <typename T>
inline constexpr size_t index_of(std::string_view name) {
constexpr auto arr = get_member_names<T>();
constexpr auto& arr = member_names<T>;
for (size_t i = 0; i < arr.size(); i++) {
if (arr[i] == name) {
return i;
Expand All @@ -136,13 +145,13 @@ inline constexpr size_t index_of() {
template <typename T, size_t index>
inline constexpr std::string_view name_of() {
static_assert(index < members_count_v<T>, "index out of range");
constexpr auto arr = get_member_names<T>();
constexpr auto& arr = member_names<T>;
return arr[index];
}

template <typename T>
inline constexpr std::string_view name_of(size_t index) {
constexpr auto arr = get_member_names<T>();
constexpr auto& arr = member_names<T>;
if (index >= arr.size()) {
return "";
}
Expand All @@ -152,7 +161,7 @@ inline constexpr std::string_view name_of(size_t index) {

template <typename T, typename Visit>
inline constexpr void for_each(Visit func) {
constexpr auto arr = get_member_names<T>();
constexpr auto& arr = member_names<T>;
[&]<size_t... Is>(std::index_sequence<Is...>) mutable {
if constexpr (std::is_invocable_v<Visit, std::string_view, size_t>) {
(func(arr[Is], Is), ...);
Expand Down
Loading

0 comments on commit b8fe6be

Please sign in to comment.