Skip to content

Commit

Permalink
Fix incorrect field names when mising :: and normal notations
Browse files Browse the repository at this point in the history
  • Loading branch information
cyanidle committed Oct 14, 2024
1 parent cf074c6 commit f035796
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@
*.exe
*.out
*.app

build/
.vscode/
.vs/
*.user
38 changes: 22 additions & 16 deletions include/describe/describe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ template<bool methods, typename...T>
constexpr size_t count() {
return ((1 * (methods == T::is_method)) + ... + 0);
}
constexpr std::string_view next_name(std::string_view& src) {

inline constexpr std::string_view next_name(std::string_view& src) {
auto resStart = src.find("::");
resStart = resStart == std::string_view::npos ? src.find_first_not_of(" ") : resStart + 2;
auto noColons = resStart == std::string_view::npos || src.find_first_of(',') < resStart;
resStart = noColons ? src.find_first_not_of(' ') : resStart + 2;
auto resEnd = src.find_first_of(" \t\n\r,", resStart);
auto result = src.substr(resStart, resEnd - resStart);
src = src.substr(src.find_first_of(',', resEnd) + 1);
Expand All @@ -54,7 +56,7 @@ auto get_attr(Attrs<Head, Ts...>) {
if constexpr (std::is_base_of_v<T, Head>) {
return Tag<Head>{};
} else {
return get_attr<T>(Attrs<Ts...>{});
return detail::get_attr<T>(Attrs<Ts...>{});
}
}

Expand All @@ -68,13 +70,17 @@ template<size_t idx, typename Head, typename...Ts> struct pack_idx : pack_idx<id
template<typename Head, typename...Ts> struct pack_idx<0, Head, Ts...> {using type = Head;};
} //detail

template<auto field> struct Field {
template<auto field>
struct Field
{
static_assert(std::is_member_pointer_v<decltype(field)> || std::is_enum_v<decltype(field)>,
"Field can only be used with &_::members or enums");
"Field can only be used with &_::members or enums");
std::string_view name;
static constexpr auto value = field;
using type = typename decltype(detail::get_memptr_type(field))::type;
static constexpr auto is_method = std::is_member_function_pointer_v<type>;
static constexpr auto is_function = std::is_function_v<type>;
static constexpr auto is_plain = std::is_member_object_pointer_v<type>;
static constexpr auto is_enum = std::is_enum_v<type>;
using cls = typename decltype(detail::get_memptr_class(field))::type;
template<typename T> static constexpr auto&& get(T&& obj) noexcept {
Expand Down Expand Up @@ -110,16 +116,16 @@ struct Description : protected Fields...
template<typename F> constexpr void for_each(F&& f) const {
(static_cast<void>(f(static_cast<const Fields&>(*this))), ...);
}
template<auto f> static constexpr size_t index_of(Field<f>) {
template<auto f> static constexpr size_t index_of(Field<f>) noexcept {
size_t result = npos;
size_t count = size_t(-1);
((count++, std::is_same_v<Field<f>, Fields> && (result = count)), ...);
return result;
}
template<auto f> static constexpr size_t index_of() {
template<auto f> static constexpr size_t index_of() noexcept {
return index_of<f>(Field<f>{});
}
constexpr size_t index_of(std::string_view name) const {
constexpr size_t index_of(std::string_view name) const noexcept {
size_t result = npos;
size_t count = size_t(-1);
((count++, (static_cast<const Fields&>(*this).name == name) && (result = count)), ...);
Expand Down Expand Up @@ -180,8 +186,8 @@ struct is_described : std::false_type {};

template<typename T>
struct is_described<T,
std::void_t<decltype(GetDescription(Tag<T>{}))
>>: std::true_type {};
std::void_t<decltype(GetDescription(Tag<T>{}))
>>: std::true_type {};

template<typename T>
constexpr auto is_described_v = is_described<T>::value;
Expand Down Expand Up @@ -230,28 +236,28 @@ friend constexpr auto GetDescription(::describe::Tag<cls>);

#define DESCRIBE(cls, ...) \
inline constexpr auto GetDescription(::describe::Tag<cls>) { using _ [[maybe_unused]] = cls; \
return _D_DESCRIBE(cls, __VA_ARGS__)(#cls, #__VA_ARGS__);}
return _D_DESCRIBE(cls, __VA_ARGS__)(#cls, #__VA_ARGS__);}

#define DESCRIBE_INHERIT(cls, parent, ...) \
inline constexpr auto GetDescription(::describe::Tag<cls>) { using _ = cls; \
return _D_DESCRIBE(cls, __VA_ARGS__)(::describe::Get<parent>(), #cls, #__VA_ARGS__);}
return _D_DESCRIBE(cls, __VA_ARGS__)(::describe::Get<parent>(), #cls, #__VA_ARGS__);}

#define DESCRIBE_TEMPL_CLASS(...) \
inline constexpr auto GetDescription(::describe::Tag<__VA_ARGS__>) { \
using _ = __VA_ARGS__; constexpr std::string_view _clsName = #__VA_ARGS__;
using _ = __VA_ARGS__; constexpr std::string_view _clsName = #__VA_ARGS__;

#define DESCRIBE_TEMPL_FIELDS(...) \
return _D_DESCRIBE(_, __VA_ARGS__)(_clsName, #__VA_ARGS__); }
return _D_DESCRIBE(_, __VA_ARGS__)(_clsName, #__VA_ARGS__); }

//! @achtung @warning THESE Should always be the same for all Translation Units
#define DESCRIBE_ATTRS(cls, ...) \
inline constexpr auto GetAttrs(::describe::Tag<cls>) { \
return ::describe::Attrs<__VA_ARGS__>{};}
return ::describe::Attrs<__VA_ARGS__>{};}

//! @achtung @warning THESE Should always be the same for all Translation Units
#define DESCRIBE_FIELD_ATTRS(cls, field, ...) \
inline constexpr auto GetAttrs(::describe::Tag<cls>, ::describe::Field<&cls::field>) { \
return ::describe::Attrs<__VA_ARGS__>{}; }
return ::describe::Attrs<__VA_ARGS__>{}; }

// Utils
template<typename T>
Expand Down
11 changes: 0 additions & 11 deletions test/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,4 @@ static_assert(std::is_same_v<object_check, in_range<0, 7>>);
using all = describe::get_attrs_t<Data>;
static_assert(std::is_same_v<all, describe::Attrs<BIG, in_range<0, 7>>>);

// Fields inherit attributes from class
constexpr auto a = describe::Get<Data>().get<0>();
using all_a = describe::get_attrs_t<decltype(a)>;
static_assert(std::is_same_v<all, all_a>);

// Unless specified for field individually
struct custom {};

constexpr auto b = describe::Get<Data>().get<0>();
using all_b = describe::get_attrs_t<decltype(a)>;
static_assert(std::is_same_v<all, all_a>);

19 changes: 11 additions & 8 deletions test/basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@ struct Data {
}
};

DESCRIBE(Data, &_::a, &_::b, &_::method)
constexpr auto r = &Data::a; //rename field
DESCRIBE(Data, r, &_::b, &_::method)

constexpr auto desc = describe::Get<Data>();
static_assert(desc.all_count == 3);
static_assert(desc.fields_count == 2);
static_assert(desc.methods_count == 1);

void print_fields(const Data& d) {
std::cout << desc.name << ": ";
desc.for_each_field([&](auto f) {
std::cout << f.name << ": " << f.get(d) << ", ";
std::cout << f.name << " -> " << f.get(d) << ", ";
});
}

void test_print() {
print_fields(Data{1, 2}); // -> a: 1, b: 2,
std::cout << std::endl;
}

enum Enum {foo, bar, baz,};
Expand All @@ -34,14 +33,18 @@ DESCRIBE(ClEnum, _::bim, _::bam, _::bom) // enum classes are supported

template<typename T>
void print_enum() {
describe::Get<T>().for_each_field([&](auto f) {
constexpr auto desc = describe::Get<T>();
std::cout << desc.name << ": ";
desc.for_each_field([&](auto f) {
using underlying = std::underlying_type_t<typename decltype(f)::type>;
std::cout << f.name << ": " << underlying(f.value) << ", ";
std::cout << f.name << " -> " << underlying(f.value) << ", ";
});
std::cout << std::endl;
}

int main(int argc, char *argv[])
{
print_fields(Data{1, 2}); // -> a: 1, b: 2,
print_enum<Enum>(); //-> foo: 0, bar: 1, baz: 2
print_enum<ClEnum>(); //-> bim: 0, bam: 1, bom: 2
}
10 changes: 4 additions & 6 deletions test/templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ DESCRIBE(test::Data<T>, &_::a, &_::b)
}

constexpr auto desc = describe::Get<test::Data<int>>();
static_assert(desc.name == "Data<T>");
static_assert(desc.ns == "test");
constexpr auto B = desc.get<1>();
static_assert(desc.name == "test::Data<T>");
constexpr auto B = describe::by_index<1>(desc);
static_assert(std::is_same_v<decltype(B)::type, int[10]>);


Expand All @@ -28,10 +27,9 @@ template<auto a, auto b> struct sum {

// DESCRIBE_CLASS(...) DESCRIBE_FIELDS(...) pair for multi-param templates
template<auto a, auto b>
DESCRIBE_CLASS(sum<a, b>)
DESCRIBE_FIELDS(&_::as_int)
DESCRIBE_TEMPL_CLASS(sum<a, b>)
DESCRIBE_TEMPL_FIELDS(&_::as_int)


constexpr auto sum_desc = describe::Get<sum<1, 2>>();
static_assert(sum_desc.name == "sum<a, b>");
static_assert(sum_desc.ns == "");

0 comments on commit f035796

Please sign in to comment.