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>
|
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>});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue