From d367f13d7bbc3d58ae8f9b0daa9ed6967f81a7df Mon Sep 17 00:00:00 2001 From: sha512sum Date: Sat, 29 Jun 2024 08:38:27 +0000 Subject: [PATCH] Add new interface for attributes --- examples/src/attributes.cpp | 22 ++++++++- include/utempl/attributes.hpp | 92 ++++++++++++++++++++++++++++++++--- 2 files changed, 106 insertions(+), 8 deletions(-) diff --git a/examples/src/attributes.cpp b/examples/src/attributes.cpp index 337c9c5..e8ab25c 100644 --- a/examples/src/attributes.cpp +++ b/examples/src/attributes.cpp @@ -4,6 +4,7 @@ template struct AttributeData { T value; + constexpr auto operator==(const AttributeData&) const -> bool = default; }; @@ -19,8 +20,25 @@ ATTRIBUTE_STRUCT(SomeStruct, std::string field3; ); -static_assert(SomeStruct::GetAttribute<0>().value == 2); -static_assert(SomeStruct::GetAttribute<2>().value == "HEY!"); +static_assert(utempl::GetAttributes() + == utempl::Tuple{ + AttributeData{.value = 2}, + utempl::NoInfo{}, + AttributeData{.value = "HEY!"}}); + + +struct SomeOtherStruct { + static_assert(utempl::OpenStruct()); + utempl::FieldAttribute, int> field1; + utempl::FieldAttribute, void> field2; + static_assert(utempl::CloseStruct()); +}; + +static_assert(utempl::GetAttributes() + == utempl::Tuple{ + utempl::kTypeList, + utempl::kTypeList}); + diff --git a/include/utempl/attributes.hpp b/include/utempl/attributes.hpp index 82e9035..ba61492 100644 --- a/include/utempl/attributes.hpp +++ b/include/utempl/attributes.hpp @@ -1,5 +1,6 @@ #include #include +#include namespace utempl { @@ -14,22 +15,70 @@ template struct AttributesCounterTag {}; -template ()> -struct CurrentSetter {}; - } // namespace impl +template < + typename T, + typename..., + auto f = []{}, + auto = AddTypeToTag() +> +consteval auto OpenStruct() -> bool { + return true; +}; +template < + typename..., + auto f = []{}, + auto I = loopholes::CountValue(), + auto II = (I > 2) ? I - 2 : I - 1, + typename T = decltype(Magic(loopholes::Getter{}>{}))::Type, + auto = AddTypeToTag() +> +consteval auto CloseStruct() -> bool { + return true; +}; + + + +struct NoInfo { + consteval auto operator==(const NoInfo&) const -> bool = default; +}; + + +template +struct FieldType { + using Type = T; +}; + + +namespace impl { + +template < + typename T, + typename... Ts, + auto f = []{}, + typename Current = decltype(GetCurrentTagType())::Type, + auto = AddTypeToTag, TypeList, decltype(f)>() +> +consteval auto FieldAttribute() -> T::Type; + +} // namespace impl + +template +using FieldAttribute = decltype(impl::FieldAttribute()); #define ATTRIBUTE_STRUCT(name, ...) struct name { \ -static_assert((::utempl::impl::CurrentSetter(), true)); \ +static_assert(::utempl::OpenStruct()); \ template \ -static consteval auto GetAttribute(); __VA_ARGS__ } +static consteval auto GetAttribute(); \ + __VA_ARGS__ \ + static_assert(::utempl::CloseStruct());\ +} -struct NoInfo {}; #define GENERIC_ATTRIBUTE(value) \ template <> \ @@ -45,4 +94,35 @@ struct NoInfo {}; #define SKIP_ATTRIBUTE() GENERIC_ATTRIBUTE(::utempl::NoInfo{}) +template < + typename T, + auto f = []{}, + bool R = (loopholes::CountValue, decltype(f)>() > 0) +> +concept HasAttributes = R; + +template +concept HasMacroAttributes = requires {T::template GetAttribute<0>();}; + + + +template +consteval auto GetAttributes() requires HasMacroAttributes { + constexpr auto I = loopholes::CountValue>(); + return [](auto... is) { + return Tuple{T::template GetAttribute()...}; + } | kSeq; +}; + +template +consteval auto GetAttributes() { + constexpr auto I = loopholes::CountValue>(); + return [](auto... is) { + return utempl::Tuple{typename decltype(Magic(loopholes::Getter>{}>{}))::Type{}...}; + } | kSeq; +}; + + + + } // namespace utempl