Add new interface for attributes

This commit is contained in:
sha512sum 2024-06-29 08:38:27 +00:00
parent 091a100f22
commit d367f13d7b
2 changed files with 106 additions and 8 deletions

View file

@ -4,6 +4,7 @@
template <typename T> template <typename T>
struct AttributeData { struct AttributeData {
T value; T value;
constexpr auto operator==(const AttributeData<T>&) const -> bool = default;
}; };
@ -19,8 +20,25 @@ ATTRIBUTE_STRUCT(SomeStruct,
std::string field3; std::string field3;
); );
static_assert(SomeStruct::GetAttribute<0>().value == 2); static_assert(utempl::GetAttributes<SomeStruct>()
static_assert(SomeStruct::GetAttribute<2>().value == "HEY!"); == utempl::Tuple{
AttributeData<int>{.value = 2},
utempl::NoInfo{},
AttributeData<std::string>{.value = "HEY!"}});
struct SomeOtherStruct {
static_assert(utempl::OpenStruct<SomeOtherStruct>());
utempl::FieldAttribute<utempl::FieldType<int>, int> field1;
utempl::FieldAttribute<utempl::FieldType<int>, void> field2;
static_assert(utempl::CloseStruct());
};
static_assert(utempl::GetAttributes<SomeOtherStruct>()
== utempl::Tuple{
utempl::kTypeList<int>,
utempl::kTypeList<void>});

View file

@ -1,5 +1,6 @@
#include <utempl/loopholes/counter.hpp> #include <utempl/loopholes/counter.hpp>
#include <utempl/meta_info.hpp> #include <utempl/meta_info.hpp>
#include <utempl/utils.hpp>
namespace utempl { namespace utempl {
@ -14,22 +15,70 @@ template <typename T>
struct AttributesCounterTag {}; struct AttributesCounterTag {};
template <typename Current, auto f = []{}, auto = AddTypeToTag<impl::AttributesTag, Current, decltype(f)>()>
struct CurrentSetter {};
} // namespace impl } // namespace impl
template <
typename T,
typename...,
auto f = []{},
auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()
>
consteval auto OpenStruct() -> bool {
return true;
};
template <
typename...,
auto f = []{},
auto I = loopholes::CountValue<impl::AttributesTag, decltype(f)>(),
auto II = (I > 2) ? I - 2 : I - 1,
typename T = decltype(Magic(loopholes::Getter<MetaInfoKey<II, impl::AttributesTag>{}>{}))::Type,
auto = AddTypeToTag<impl::AttributesTag, T, decltype(f)>()
>
consteval auto CloseStruct() -> bool {
return true;
};
struct NoInfo {
consteval auto operator==(const NoInfo&) const -> bool = default;
};
template <typename T>
struct FieldType {
using Type = T;
};
namespace impl {
template <
typename T,
typename... Ts,
auto f = []{},
typename Current = decltype(GetCurrentTagType<impl::AttributesTag, decltype(f)>())::Type,
auto = AddTypeToTag<impl::AttributesCounterTag<Current>, TypeList<Ts...>, decltype(f)>()
>
consteval auto FieldAttribute() -> T::Type;
} // namespace impl
template <typename... Ts>
using FieldAttribute = decltype(impl::FieldAttribute<Ts...>());
#define ATTRIBUTE_STRUCT(name, ...) struct name { \ #define ATTRIBUTE_STRUCT(name, ...) struct name { \
static_assert((::utempl::impl::CurrentSetter<name>(), true)); \ static_assert(::utempl::OpenStruct<name>()); \
template <std::size_t N> \ template <std::size_t N> \
static consteval auto GetAttribute(); __VA_ARGS__ } static consteval auto GetAttribute(); \
__VA_ARGS__ \
static_assert(::utempl::CloseStruct());\
}
struct NoInfo {};
#define GENERIC_ATTRIBUTE(value) \ #define GENERIC_ATTRIBUTE(value) \
template <> \ template <> \
@ -45,4 +94,35 @@ struct NoInfo {};
#define SKIP_ATTRIBUTE() GENERIC_ATTRIBUTE(::utempl::NoInfo{}) #define SKIP_ATTRIBUTE() GENERIC_ATTRIBUTE(::utempl::NoInfo{})
template <
typename T,
auto f = []{},
bool R = (loopholes::CountValue<impl::AttributesCounterTag<T>, decltype(f)>() > 0)
>
concept HasAttributes = R;
template <typename T>
concept HasMacroAttributes = requires {T::template GetAttribute<0>();};
template <HasAttributes T>
consteval auto GetAttributes() requires HasMacroAttributes<T> {
constexpr auto I = loopholes::CountValue<impl::AttributesCounterTag<T>>();
return [](auto... is) {
return Tuple{T::template GetAttribute<is>()...};
} | kSeq<I>;
};
template <typename T>
consteval auto GetAttributes() {
constexpr auto I = loopholes::CountValue<impl::AttributesCounterTag<T>>();
return [](auto... is) {
return utempl::Tuple{typename decltype(Magic(loopholes::Getter<MetaInfoKey<is, impl::AttributesCounterTag<T>>{}>{}))::Type{}...};
} | kSeq<I>;
};
} // namespace utempl } // namespace utempl