Add new interface for attributes
This commit is contained in:
parent
091a100f22
commit
d367f13d7b
2 changed files with 106 additions and 8 deletions
|
@ -4,6 +4,7 @@
|
|||
template <typename T>
|
||||
struct AttributeData {
|
||||
T value;
|
||||
constexpr auto operator==(const AttributeData<T>&) 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<SomeStruct>()
|
||||
== 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>});
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <utempl/loopholes/counter.hpp>
|
||||
#include <utempl/meta_info.hpp>
|
||||
#include <utempl/utils.hpp>
|
||||
|
||||
|
||||
namespace utempl {
|
||||
|
@ -14,22 +15,70 @@ template <typename T>
|
|||
struct AttributesCounterTag {};
|
||||
|
||||
|
||||
template <typename Current, auto f = []{}, auto = AddTypeToTag<impl::AttributesTag, Current, decltype(f)>()>
|
||||
struct CurrentSetter {};
|
||||
|
||||
|
||||
} // 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 { \
|
||||
static_assert((::utempl::impl::CurrentSetter<name>(), true)); \
|
||||
static_assert(::utempl::OpenStruct<name>()); \
|
||||
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) \
|
||||
template <> \
|
||||
|
@ -45,4 +94,35 @@ struct 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
|
||||
|
|
Loading…
Reference in a new issue