#pragma once #include "fixed_string.hpp" #include #include #include #include namespace structive { template struct Member_Property_Dependency { static constexpr auto member = Member; }; template struct Key_Property_Dependency { static constexpr auto key = Key; }; template struct Property_Dependencies { using property_dependencies_tag = void; static constexpr std::size_t count = sizeof...(Dependencies); }; template concept Property_Dependencies_Type = requires { typename Type::property_dependencies_tag; { Type::count } -> std::convertible_to; }; template inline constexpr Property_Dependencies...> depends_on{}; template inline constexpr Property_Dependencies...> depends_on_keys{}; using No_Property_Dependencies = Property_Dependencies<>; template struct Member_Pointer_Traits; template struct Member_Pointer_Traits { using object_type = Object; using value_type = Value; }; template struct Member_Function_Traits; template struct Member_Function_Traits { using object_type = Object; using return_type = Return; }; template struct Member_Function_Traits { using object_type = Object; using return_type = Return; }; template struct Member_Function_Traits : Member_Function_Traits {}; template struct Member_Function_Traits : Member_Function_Traits {}; template struct Member_Storage_Identity {}; template concept Trusted_Getter_Function = requires { typename Member_Function_Traits::object_type; } && requires(const typename Member_Function_Traits::object_type& object) { std::invoke(Getter, object); } && (!std::is_void_v::object_type&>>) && (!std::is_rvalue_reference_v::object_type&>>) && (!(std::is_lvalue_reference_v::object_type&>> && !std::is_const_v::object_type&>>>)); template using trusted_getter_object_t = typename Member_Function_Traits::object_type; template using trusted_getter_value_t = std::remove_cvref_t&>>; template concept Trusted_Setter_Function_For = requires { typename Member_Function_Traits::object_type; } && std::same_as::object_type, Object> && requires(Object& object, Value value) { { std::invoke(Setter, object, std::move(value)) } -> std::same_as; }; template struct Member_Accessor { using traits = Member_Pointer_Traits; using object_type = typename traits::object_type; using value_type = typename traits::value_type; using storage_identity = Member_Storage_Identity; static constexpr bool readable = true; static constexpr bool writable = !std::is_const_v; static constexpr bool synchronized_view_read = false; static constexpr bool trusted_object_access = false; using dependency_spec = No_Property_Dependencies; static constexpr auto member = Member; constexpr const value_type& read(const object_type& object) const { return object.*Member; } constexpr value_type& read(object_type& object) const { return object.*Member; } template constexpr void write(object_type& object, Value&& value) const requires writable && std::assignable_from { object.*Member = std::forward(value); } }; template struct Synchronized_Computed_Accessor { using object_type = Object; using value_type = Value; using storage_identity = void; static constexpr bool readable = true; static constexpr bool writable = false; static constexpr bool synchronized_view_read = true; static constexpr bool trusted_object_access = false; using dependency_spec = Dependencies; [[no_unique_address]] Function function; template constexpr value_type read(const View& view) const requires std::invocable && std::constructible_from> { return value_type(std::invoke(function, view)); } }; template requires Trusted_Getter_Function struct Trusted_Computed_Accessor { using object_type = trusted_getter_object_t; using value_type = trusted_getter_value_t; using storage_identity = void; static constexpr bool readable = true; static constexpr bool writable = false; static constexpr bool synchronized_view_read = false; static constexpr bool trusted_object_access = true; using dependency_spec = No_Property_Dependencies; constexpr decltype(auto) read(const object_type& object) const noexcept(std::is_nothrow_invocable_v) { return std::invoke(Getter, object); } }; template requires Trusted_Getter_Function && Trusted_Setter_Function_For, trusted_getter_value_t> struct Trusted_Getter_Setter_Accessor { using object_type = trusted_getter_object_t; using value_type = trusted_getter_value_t; using storage_identity = void; static constexpr bool readable = true; static constexpr bool writable = true; static constexpr bool synchronized_view_read = false; static constexpr bool trusted_object_access = true; using dependency_spec = No_Property_Dependencies; constexpr decltype(auto) read(const object_type& object) const noexcept(std::is_nothrow_invocable_v) { return std::invoke(Getter, object); } template constexpr void write(object_type& object, Value&& value) const requires std::invocable && std::same_as, void> { std::invoke(Setter, object, std::forward(value)); } }; template concept Property_Accessor = requires { typename Accessor::object_type; typename Accessor::value_type; typename Accessor::storage_identity; typename Accessor::dependency_spec; requires Property_Dependencies_Type; { Accessor::readable } -> std::convertible_to; { Accessor::writable } -> std::convertible_to; { Accessor::synchronized_view_read } -> std::convertible_to; { Accessor::trusted_object_access } -> std::convertible_to; }; }