Skip to content

Commit

Permalink
refactor: unmangle strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
Curve committed Oct 20, 2024
1 parent 3bcef7c commit 2430d83
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 77 deletions.
4 changes: 2 additions & 2 deletions include/rebind/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ namespace rebind::impl
template <typename U>
consteval auto unmangle(std::string_view name, U decorators)
{
const auto start = name.substr(name.rfind(decorators.first) + decorators.first.size());
const auto end = start.substr(0, start.rfind(decorators.second));
const auto start = name.substr(0, name.rfind(decorators.second));
const auto end = start.substr(start.rfind(decorators.first) + decorators.first.size());

return end;
}
Expand Down
119 changes: 48 additions & 71 deletions include/rebind/member.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,123 +17,100 @@ namespace rebind

namespace impl
{
template <typename T>
extern T external;

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#endif
template <typename T, std::size_t I>
static consteval decltype(auto) member_at()
template <typename T>
struct dummy
{
return std::get<I>(to_tuple(external<T>));
T value;

public:
static const dummy<T> instance;
};

template <typename T>
static constexpr auto member_count = []
consteval auto &dummy_value()
{
return std::tuple_size_v<decltype(to_tuple(external<T>))>;
}();
return dummy<T>::instance.value;
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif

struct some_ref
template <typename T, std::size_t I>
consteval decltype(auto) member_at()
{
int find_me;
return std::get<I>(to_tuple(dummy_value<T>()));
};

static constexpr auto external_decorators = []
{
constexpr auto member = &member_at<some_ref, 0>();
constexpr auto mangled = mangled_name<member>();

constexpr std::string_view instance = "external";
constexpr std::string_view name = "find_me";

constexpr auto start = mangled.find(instance);
constexpr auto end = mangled.rfind(name);

constexpr auto prefix = mangled.substr(0, start + instance.size());
constexpr auto suffix = mangled.substr(end + name.size());

return std::make_pair(prefix, suffix);
}();

template <auto T>
static constexpr auto unmangle_external = []
template <typename T>
struct pointer // MSVC workaround
{
constexpr auto mangled = mangled_name<T>();
constexpr auto decorators = external_decorators;

return unmangle(mangled, decorators);
}();
const T *value;
};

static constexpr auto member_decorators = []
struct unmangle_me
{
constexpr auto member = &member_at<some_ref, 0>();
constexpr auto mangled = unmangle_external<member>;

constexpr std::string_view type = "some_ref";
constexpr std::string_view name = "find_me";

constexpr auto type_pos = mangled.rfind(type);
constexpr auto name_pos = mangled.rfind(name);

constexpr auto start = type_pos == std::string_view::npos ? 0 : type_pos + type.size();

constexpr auto prefix = mangled.substr(start, name_pos - start);
constexpr auto suffix = mangled.substr(name_pos + name.size());
int find_me;
};

return std::make_pair(prefix, suffix);
}();
static constexpr auto member_decorators = name_decorators<pointer{&member_at<unmangle_me, 0>()}>("find_me");

template <auto T>
static constexpr auto unmangle_member = []
{
constexpr auto mangled = unmangle_external<T>;
constexpr auto mangled = mangled_name<pointer{T}>();
constexpr auto decorators = member_decorators;

return unmangle(mangled, decorators);
}();

template <typename T>
requires std::is_aggregate_v<T>
static constexpr auto members = []
consteval auto unpack_members()
{
constexpr auto unpack = []<auto... Is>(std::index_sequence<Is...>)
{
auto unpack_at = []<auto I>(constant<I>)
{
constexpr auto &member = member_at<T, I>();
constexpr auto arity = rebind::arity<T>;

return rebind::member<std::remove_reference_t<decltype(member)>>{
.index = I,
.name = unmangle_member<&member>,
};
};
const auto unpack = []<auto I>(constant<I>)
{
constexpr auto &member = member_at<T, I>();
using member_t = std::remove_cvref_t<decltype(member)>;
return rebind::member<member_t>{.index = I, .name = unmangle_member<&member>};
};

return std::make_tuple(unpack_at(constant<Is>{})...);
const auto unpack_sequence = [unpack]<auto... Is>(std::index_sequence<Is...>)
{
return std::make_tuple(unpack(constant<Is>{})...);
};

return unpack(std::make_index_sequence<member_count<T>>{});
return unpack_sequence(std::make_index_sequence<arity>());
}

template <typename T>
requires std::is_aggregate_v<T>
static constexpr auto members = []
{
return unpack_members<T>();
}();

template <auto T, typename C, typename V>
template <auto T>
requires std::is_member_pointer_v<decltype(T)>
consteval auto member_name(V C::*)
static constexpr auto member_name = []
{
constexpr auto name = rebind::nttp_name<T>;
constexpr auto type = rebind::type_name<C>;
constexpr auto type = []<class C>(auto C::*)
{
return rebind::type_name<C>;
}(T);

return remove_type(name, type, "::");
}
}();
} // namespace impl

template <typename T>
static constexpr auto members = impl::members<T>;

template <auto T>
static constexpr auto member_name = impl::member_name<T>(T);
static constexpr auto member_name = impl::member_name<T>;
} // namespace rebind
2 changes: 1 addition & 1 deletion include/rebind/name.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace rebind
constexpr auto mangled = mangled_name<T>();
const auto start = mangled.find(needle);

const auto prefix = mangled.substr(0, start);
const auto prefix = mangled.substr(start - 1, 1);
const auto suffix = mangled.substr(start + needle.size());

return std::make_pair(prefix, suffix);
Expand Down
4 changes: 2 additions & 2 deletions tests/enum.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ suite<"enum"> enum_test = []()
expect(rebind::enum_name<some_enum::a> == "a");
expect(rebind::enum_name<some_enum::b> == "b");

constexpr auto values = rebind::enum_values<some_enum>;
static constexpr auto values = rebind::enum_values<some_enum>;

expect(values.size() == 3);

Expand All @@ -54,7 +54,7 @@ suite<"enum"> enum_test = []()
expect(rebind::enum_name<ns::another_enum::x> == "x");
expect(rebind::enum_name<ns::another_enum::y> == "y");

constexpr auto values = rebind::enum_values<ns::another_enum>;
static constexpr auto values = rebind::enum_values<ns::another_enum>;

expect(values.size() == 3);

Expand Down
11 changes: 10 additions & 1 deletion tests/member.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,32 @@ suite<"member"> member_test = []()
expect(rebind::member_name<&simple::z> == "z");
expect(rebind::member_name<&simple::inner> == "inner");

constexpr auto members = rebind::members<simple>;
static constexpr auto members = rebind::members<simple>;
static constexpr auto inner_members = rebind::members<decltype(simple{}.inner)>;

expect(std::tuple_size_v<decltype(members)> == 4);
expect(std::tuple_size_v<decltype(inner_members)> == 1);

expect(std::get<0>(members).name == "x");
expect(std::get<1>(members).name == "y");
expect(std::get<2>(members).name == "z");

expect(std::get<3>(members).name == "inner");
expect(std::get<0>(inner_members).name == "test");

expect(std::get<0>(members).index == 0);
expect(std::get<1>(members).index == 1);
expect(std::get<2>(members).index == 2);

expect(std::get<3>(members).index == 3);
expect(std::get<0>(inner_members).index == 0);

expect(std::same_as<std::tuple_element_t<0, decltype(members)>::type, int>);
expect(std::same_as<std::tuple_element_t<1, decltype(members)>::type, float>);
expect(std::same_as<std::tuple_element_t<2, decltype(members)>::type, double>);

expect(std::is_class_v<std::tuple_element_t<3, decltype(members)>::type>);
expect(std::same_as<std::tuple_element_t<0, decltype(inner_members)>::type, bool>);

simple instance{1, 2, 3, {true}};

Expand Down

0 comments on commit 2430d83

Please sign in to comment.