Skip to content

Commit

Permalink
Merge pull request #259 from qicosmos/support_name_of
Browse files Browse the repository at this point in the history
  • Loading branch information
qicosmos authored Apr 29, 2024
2 parents fdfdac2 + adfeb21 commit fb6e6d5
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++20")
add_compile_options(/utf-8)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/bigobj>")
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/Zc:__cplusplus>")
else()

if(NOT LINKLIBC++)
Expand Down
10 changes: 9 additions & 1 deletion iguana/detail/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

#include "iguana/define.h"


namespace iguana {

template <class T>
Expand Down Expand Up @@ -68,6 +67,15 @@ template <typename T, typename... Us>
struct has_type<T, std::tuple<Us...>>
: std::disjunction<std::is_same<T, Us>...> {};

template <class T>
struct member_tratis {};

template <class T, class Owner>
struct member_tratis<T Owner::*> {
using owner_type = Owner;
using value_type = T;
};

template <typename T>
inline constexpr bool is_int64_v =
std::is_same_v<T, int64_t> || std::is_same_v<T, uint64_t>;
Expand Down
89 changes: 89 additions & 0 deletions iguana/reflection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -910,6 +910,95 @@ constexpr const std::string_view get_name() {
return M::name();
}

namespace detail {
#if __cplusplus < 201703L
template <auto ptr, auto ele>
constexpr bool get_index_imple() {
if constexpr (std::is_same_v<
typename member_tratis<decltype(ptr)>::value_type,
typename member_tratis<decltype(ele)>::value_type>) {
if constexpr (ele == ptr) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}

#define member_index(ptr, tp) \
[&]<size_t... I>(std::index_sequence<I...>) { \
bool r = false; \
size_t index = 0; \
((void)(!r && (r = detail::get_index_imple<ptr, std::get<I>(tp)>(), \
!r ? index++ : index, true)), \
...); \
return index; \
} \
(std::make_index_sequence<std::tuple_size_v<decltype(tp)>>{});
#else
template <typename T, typename U>
constexpr bool get_index_imple(T ptr, U ele) {
if constexpr (std::is_same_v<
typename iguana::member_tratis<decltype(ptr)>::value_type,
typename iguana::member_tratis<
decltype(ele)>::value_type>) {
if (ele == ptr) {
return true;
}
else {
return false;
}
}
else {
return false;
}
}

template <typename T, typename Tuple, size_t... I>
constexpr size_t member_index_impl(T ptr, Tuple &tp,
std::index_sequence<I...>) {
bool r = false;
size_t index = 0;
((void)(!r && (r = get_index_imple(ptr, std::get<I>(tp)),
!r ? index++ : index, true)),
...);
return index;
}

template <typename T, typename Tuple>
constexpr size_t member_index(T ptr, Tuple &tp) {
return member_index_impl(
ptr, tp,
std::make_index_sequence<
std::tuple_size_v<std::decay_t<decltype(tp)>>>{});
}
#endif
} // namespace detail

template <auto member>
constexpr size_t index_of() {
using namespace detail;
using T = typename member_tratis<decltype(member)>::owner_type;
using M = Reflect_members<T>;
constexpr auto tp = M::apply_impl();
constexpr size_t Size = std::tuple_size_v<decltype(tp)>;
constexpr size_t index = member_index(member, tp);
static_assert(index < Size, "out of range");
return index;
}

template <auto member>
constexpr auto name_of() {
using T = typename member_tratis<decltype(member)>::owner_type;
using M = Reflect_members<T>;
constexpr auto s = M::arr()[index_of<member>()];
return std::string_view(s.data(), s.size());
}

template <typename T>
constexpr const std::string_view get_fields() {
using M = Reflect_members<T>;
Expand Down
18 changes: 18 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,24 @@ TEST_CASE("parse some other char") {
CHECK(p.name == "tom");
}

TEST_CASE("index_of name_of") {
constexpr size_t idx1 = iguana::index_of<&point_t::y>();
static_assert(idx1 == 1);
constexpr size_t idx2 = iguana::index_of<&person::name>();
static_assert(idx2 == 0);

CHECK(idx1 == 1);
CHECK(idx2 == 0);

constexpr auto s1 = iguana::name_of<&point_t::y>();
static_assert(s1 == "y");
constexpr auto s2 = iguana::name_of<&person::name>();
static_assert(s2 == "name");

CHECK(s1 == "y");
CHECK(s2 == "name");
}

TEST_CASE("check some types") {
using value_type = std::variant<int point_t::*, double point_t::*>;
constexpr auto map = iguana::get_iguana_struct_map<point_t>();
Expand Down

0 comments on commit fb6e6d5

Please sign in to comment.