#pragma once #include "accessor.hpp" #include "attributes.hpp" #include "meta.hpp" #include #include #include #include #include namespace structive { template consteval bool constraints_compatible() { return (([] { if constexpr (Property_Constraint) { return Property_Constraint_For; } return true; }()) && ...); } template struct Property_Descriptor { using property_descriptor_tag = void; using accessor_type = Accessor; using object_type = typename Accessor::object_type; using value_type = typename Accessor::value_type; using storage_identity = typename Accessor::storage_identity; using attribute_types = Type_List; static constexpr bool readable = Accessor::readable; static constexpr bool writable = Accessor::writable; static constexpr bool synchronized_view_read = Accessor::synchronized_view_read; static constexpr bool trusted_object_access = Accessor::trusted_object_access; static_assert(unique_single_value_categories()); using key_type = find_attribute_in_list_t; static_assert(!std::same_as); static_assert(key_type::value.view().size() > 0); static_assert(constraints_compatible()); [[no_unique_address]] Accessor accessor{}; std::tuple attributes; template using attribute_type = find_attribute_in_list_t; template static constexpr bool has_attribute = !std::same_as, void>; template constexpr decltype(auto) attribute() const requires has_attribute { using target = attribute_type; return std::get(attributes); } constexpr std::string_view key() const noexcept { return key_type::value.view(); } template constexpr void for_each_attribute(Function&& function) const { std::apply([&](const auto&... values) { (function(values), ...); }, attributes); } template constexpr void for_each_constraint(Function&& function) const { std::apply([&](const auto&... values) { ([&] { using type = std::remove_cvref_t; if constexpr (Property_Constraint) { function(values); } }(), ...); }, attributes); } }; template concept Property_Descriptor_Type = requires { typename Type::property_descriptor_tag; typename Type::object_type; typename Type::value_type; typename Type::accessor_type; typename Type::storage_identity; }; template constexpr auto property(Attributes&&... attributes) { using accessor = Member_Accessor; return Property_Descriptor...>{{}, {std::forward(attributes)...}}; } template constexpr auto field(Attributes&&... attributes) { return property(std::forward(attributes)...); } template constexpr auto computed_property(Function&& function, Attributes&&... attributes) { using accessor = Synchronized_Computed_Accessor>; return Property_Descriptor...>{accessor{std::forward(function)}, {std::forward(attributes)...}}; } template requires Trusted_Getter_Function constexpr auto trusted_computed_property(Attributes&&... attributes) { using accessor = Trusted_Computed_Accessor; return Property_Descriptor...>{{}, {std::forward(attributes)...}}; } template requires Trusted_Getter_Function && Trusted_Setter_Function_For, trusted_getter_value_t> constexpr auto trusted_accessor_property(Attributes&&... attributes) { using accessor = Trusted_Getter_Setter_Accessor; return Property_Descriptor...>{{}, {std::forward(attributes)...}}; } }