include/ylt/reflection/member_ptr.hpp (119 lines of code) (raw):
#pragma once
#include "member_count.hpp"
// modified based on:
// https://github.com/getml/reflect-cpp/blob/main/include/rfl/internal/bind_fake_object_to_tuple.hpp
// thanks for alxn4's great idea!
namespace ylt::reflection {
namespace internal {
template <class T, std::size_t n>
struct object_tuple_view_helper {
static constexpr auto tuple_view() {
static_assert(
sizeof(T) < 0,
"\n\nThis error occurs for one of two reasons:\n\n"
"1) You have created a struct with more than 256 fields, which is "
"unsupported. \n\n"
"2) Your struct is not an aggregate type. You can make it aggregated, "
"or defined a YLT_REFL macro. \n\n");
}
static constexpr auto tuple_view(T&) {
static_assert(
sizeof(T) < 0,
"\n\nThis error occurs for one of two reasons:\n\n"
"1) You have created a struct with more than 256 fields, which is "
"unsupported. \n\n"
"2) Your struct is not an aggregate type. You can make it aggregated, "
"or defined a YLT_REFL macro. \n\n");
}
template <typename Visitor>
static constexpr decltype(auto) tuple_view(T&&, Visitor&&) {
static_assert(
sizeof(T) < 0,
"\n\nThis error occurs for one of two reasons:\n\n"
"1) You have created a struct with more than 256 fields, which is "
"unsupported. \n\n"
"2) Your struct is not an aggregate type. You can make it aggregated, "
"or defined a YLT_REFL macro. \n\n");
}
};
template <class T>
struct object_tuple_view_helper<T, 0> {
static constexpr auto tuple_view() { return std::tie(); }
static constexpr auto tuple_view(T&) { return std::tie(); }
template <typename Visitor>
static constexpr decltype(auto) tuple_view(T&&, Visitor&&) {}
};
template <class T>
struct wrapper {
inline static remove_cvref_t<T> value;
};
template <class T>
inline constexpr remove_cvref_t<T>& get_fake_object() noexcept {
return wrapper<remove_cvref_t<T>>::value;
}
#define RFL_INTERNAL_OBJECT_IF_YOU_SEE_AN_ERROR_REFER_TO_DOCUMENTATION_ON_C_ARRAYS( \
n, ...) \
template <class T> \
struct object_tuple_view_helper<T, n> { \
static constexpr auto tuple_view() { \
auto& [__VA_ARGS__] = get_fake_object<remove_cvref_t<T>>(); \
auto ref_tup = std::tie(__VA_ARGS__); \
auto get_ptrs = [](auto&... _refs) { \
return std::make_tuple(&_refs...); \
}; \
return std::apply(get_ptrs, ref_tup); \
} \
static constexpr auto tuple_view(T& t) { \
auto& [__VA_ARGS__] = t; \
return std::tie(__VA_ARGS__); \
} \
template <typename Visitor> \
static constexpr decltype(auto) tuple_view(T&& t, Visitor&& visitor) { \
auto&& [__VA_ARGS__] = t; \
return visitor(__VA_ARGS__); \
} \
}
// such file is generate macro file
#include "internal/generate/member_macro.hpp"
template <class T>
inline constexpr auto tuple_view(T&& t) {
return internal::object_tuple_view_helper<T, members_count_v<T>>::tuple_view(
t);
}
template <size_t Count, class T, typename Visitor>
inline constexpr decltype(auto) tuple_view(T&& t, Visitor&& visitor) {
return internal::object_tuple_view_helper<T, Count>::tuple_view(
std::forward<T>(t), std::forward<Visitor>(visitor));
}
} // namespace internal
template <class T>
inline constexpr auto struct_to_tuple() {
return internal::object_tuple_view_helper<T,
members_count_v<T>>::tuple_view();
}
template <class T>
inline constexpr auto object_to_tuple(T&& t) {
using type = remove_cvref_t<T>;
if constexpr (is_out_ylt_refl_v<type>) {
return refl_object_to_tuple(std::forward<T>(t));
}
else if constexpr (is_inner_ylt_refl_v<type>) {
return type::refl_object_to_tuple(std::forward<T>(t));
}
else {
return internal::tuple_view(std::forward<T>(t));
}
}
template <class T, typename Visitor, size_t Count = members_count_v<T>>
inline constexpr decltype(auto) visit_members(T&& t, Visitor&& visitor) {
using type = remove_cvref_t<T>;
if constexpr (is_out_ylt_refl_v<type>) {
return refl_visit_members(std::forward<T>(t),
std::forward<Visitor>(visitor));
}
else if constexpr (is_inner_ylt_refl_v<type>) {
return t.refl_visit_members(std::forward<T>(t),
std::forward<Visitor>(visitor));
}
else {
return internal::tuple_view<Count>(std::forward<T>(t),
std::forward<Visitor>(visitor));
}
}
} // namespace ylt::reflection