diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-18 10:42:26 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-11-18 10:42:26 +0100 |
commit | b65b34a976b586f4e407f7a89567163c85b94aa6 (patch) | |
tree | 3c7ca19603fbe6b76dc9b24511a23b337a1c341d | |
parent | 41d3bbf3f3783b70a4a47e18478c227d12e73b06 (diff) |
split erased accessor from main header
-rw-r--r-- | entity/accessor.hpp | 112 | ||||
-rw-r--r-- | entity/entity.hpp (renamed from src/entity.hpp) | 107 | ||||
-rw-r--r-- | entity/name-of.hpp | 18 | ||||
-rw-r--r-- | entity/util.hpp | 22 | ||||
-rw-r--r-- | test/entity.cpp | 2 |
5 files changed, 156 insertions, 105 deletions
diff --git a/entity/accessor.hpp b/entity/accessor.hpp new file mode 100644 index 00000000..9b836420 --- /dev/null +++ b/entity/accessor.hpp @@ -0,0 +1,112 @@ +#pragma once +#include "util.hpp" +#include <type_traits> +#include <Corrade/Containers/StringView.h> + +namespace floormat::entities { + +struct erased_accessor final { + using erased_reader_t = void; + using erased_writer_t = void; + using Object = void; + using Value = void; + + const erased_reader_t* reader; + const erased_writer_t* writer; + StringView object_name, field_type_name; + void(*read_fun)(const Object*, const erased_reader_t*, Value*); + void(*write_fun)(Object*, const erased_writer_t*, Value*); + + constexpr erased_accessor(const erased_accessor&) = default; + constexpr erased_accessor(erased_reader_t* reader, erased_writer_t * writer, + StringView object_name, StringView field_type_name, + void(*read_fun)(const Object*, const erased_reader_t*, Value*), + void(*write_fun)(Object*, const erased_writer_t*, Value*)) : + reader{reader}, writer{writer}, + object_name{object_name}, field_type_name{field_type_name}, + read_fun{read_fun}, write_fun{write_fun} + {} + + template<typename T, typename FieldType> + static constexpr bool check_name_static(); + + template<typename T, typename FieldType> + constexpr bool check_name() const noexcept; + + template<typename Obj, typename FieldType> constexpr void assert_name() const noexcept; + template<typename Obj, typename FieldType> void read_unchecked(const Obj& x, FieldType& value) const noexcept; + template<typename Obj, typename FieldType> requires std::is_default_constructible_v<FieldType> FieldType read_unchecked(const Obj& x) const noexcept; + template<typename Obj, typename FieldType> void write_unchecked(Obj& x, move_qualified<FieldType> value) const noexcept; + template<typename Obj, typename FieldType> requires std::is_default_constructible_v<FieldType> FieldType read(const Obj& x) const noexcept; + template<typename Obj, typename FieldType> void read(const Obj& x, FieldType& value) const noexcept; + template<typename Obj, typename FieldType> void write(Obj& x, move_qualified<FieldType> value) const noexcept; +}; + +template<typename T, typename FieldType> +constexpr bool erased_accessor::check_name_static() +{ + return !std::is_pointer_v<T> && !std::is_reference_v<T> && + !std::is_pointer_v<FieldType> && !std::is_reference_v<T>; +} + +template<typename T, typename FieldType> +constexpr bool erased_accessor::check_name() const noexcept +{ + static_assert(check_name_static<T, FieldType>()); + constexpr auto obj = name_of<T>, field = name_of<FieldType>; + return (obj.data() == object_name.data() && field.data() == field_type_name.data()) || + obj == object_name && field == field_type_name; +} + +template<typename Obj, typename FieldType> +constexpr void erased_accessor::assert_name() const noexcept +{ + fm_assert(check_name<Obj, FieldType>()); +} + +template<typename Obj, typename FieldType> +void erased_accessor::read_unchecked(const Obj& x, FieldType& value) const noexcept +{ + static_assert(check_name_static<Obj, FieldType>()); + read_fun(&x, reader, &value); +} + +template<typename Obj, typename FieldType> +requires std::is_default_constructible_v<FieldType> +FieldType erased_accessor::read_unchecked(const Obj& x) const noexcept +{ + static_assert(check_name_static<Obj, FieldType>()); + FieldType value; + read_unchecked(x, value); + return value; +} + +template<typename Obj, typename FieldType> +void erased_accessor::write_unchecked(Obj& x, move_qualified<FieldType> value) const noexcept +{ + static_assert(check_name_static<Obj, FieldType>()); + write_fun(&x, writer, &value); +} + +template<typename Obj, typename FieldType> +requires std::is_default_constructible_v<FieldType> +FieldType erased_accessor::read(const Obj& x) const noexcept { + assert_name<Obj, FieldType>(); + return read_unchecked<Obj, FieldType>(x); +} + +template<typename Obj, typename FieldType> +void erased_accessor::read(const Obj& x, FieldType& value) const noexcept +{ + assert_name<Obj, FieldType>(); + read_unchecked<Obj, FieldType>(x, value); +} + +template<typename Obj, typename FieldType> +void erased_accessor::write(Obj& x, move_qualified<FieldType> value) const noexcept +{ + assert_name<Obj, FieldType>(); + write_unchecked<Obj, FieldType>(x, value); +} + +} // namespace floormat::entities diff --git a/src/entity.hpp b/entity/entity.hpp index 0f7ccbe0..8f0980ae 100644 --- a/src/entity.hpp +++ b/entity/entity.hpp @@ -1,5 +1,8 @@ #pragma once +#include "name-of.hpp" #include "compat/integer-types.hpp" +#include "accessor.hpp" +#include "util.hpp" #include <concepts> #include <compare> #include <type_traits> @@ -10,33 +13,8 @@ #include <compat/function2.hpp> #include <Corrade/Containers/StringView.h> -#if defined _MSC_VER -#define FM_PRETTY_FUNCTION __FUNCSIG__ -#else -#define FM_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#endif - -template<typename T> -static constexpr auto _name_of() { - using namespace Corrade::Containers; - using SVF = StringViewFlag; - constexpr const char* str = FM_PRETTY_FUNCTION; - return StringView { str, Implementation::strlen_(str), SVF::Global|SVF::NullTerminated }; -} - -template<typename T> constexpr inline Corrade::Containers::StringView name_of = _name_of<T>(); - namespace floormat::entities { -template<typename T, typename = void> struct pass_by_value : std::bool_constant<std::is_fundamental_v<T>> {}; -template<> struct pass_by_value<StringView> : std::true_type {}; -template<typename T> struct pass_by_value<T, std::enable_if_t<std::is_trivially_copy_constructible_v<T> && sizeof(T) <= sizeof(void*)>> : std::true_type {}; -template<typename T> constexpr inline bool pass_by_value_v = pass_by_value<T>::value; - -template<typename T> using const_qualified = std::conditional_t<pass_by_value_v<T>, T, const T&>; -template<typename T> using ref_qualified = std::conditional_t<pass_by_value_v<T>, T, T&>; -template<typename T> using move_qualified = std::conditional_t<pass_by_value_v<T>, T, T&&>; - template<typename F, typename T, typename FieldType> concept FieldReader_memfn = requires(const T x, F f) { { (x.*f)() } -> std::convertible_to<FieldType>; @@ -167,85 +145,6 @@ using accessors_for = typename accessors_for_<T>::type; } // namespace detail -struct erased_accessor final { - using erased_reader_t = void; - using erased_writer_t = void; - using Object = void; - using Value = void; - - const erased_reader_t* reader; - const erased_writer_t* writer; - StringView object_name, field_type_name; - void(*read_fun)(const Object*, const erased_reader_t*, Value*); - void(*write_fun)(Object*, const erased_writer_t*, Value*); - - constexpr erased_accessor(const erased_accessor&) = default; - constexpr erased_accessor(erased_reader_t* reader, erased_writer_t * writer, - StringView object_name, StringView field_type_name, - void(*read_fun)(const Object*, const erased_reader_t*, Value*), - void(*write_fun)(Object*, const erased_writer_t*, Value*)) : - reader{reader}, writer{writer}, - object_name{object_name}, field_type_name{field_type_name}, - read_fun{read_fun}, write_fun{write_fun} - {} - - template<typename T, typename FieldType> - static constexpr bool check_name_static() - { - return !std::is_pointer_v<T> && !std::is_reference_v<T> && - !std::is_pointer_v<FieldType> && !std::is_reference_v<T>; - } - - template<typename T, typename FieldType> - constexpr bool check_name() const noexcept - { - static_assert(check_name_static<T, FieldType>()); - constexpr auto obj = name_of<T>, field = name_of<FieldType>; - return (obj.data() == object_name.data() && field.data() == field_type_name.data()) || - obj == object_name && field == field_type_name; - } - - template<typename Obj, typename FieldType> - constexpr void assert_name() const noexcept - { - fm_assert(check_name<Obj, FieldType>()); - } - - template<typename Obj, typename FieldType> - void read_unchecked(const Obj& x, FieldType& value) const noexcept - { - static_assert(check_name_static<Obj, FieldType>()); - read_fun(&x, reader, &value); - } - - template<typename Obj, typename FieldType> - requires std::is_default_constructible_v<FieldType> - FieldType read_unchecked(const Obj& x) const noexcept - { - static_assert(check_name_static<Obj, FieldType>()); - FieldType value; - read_unchecked(x, value); - return value; - } - - template<typename Obj, typename FieldType> - void write_unchecked(Obj& x, move_qualified<FieldType> value) const noexcept - { - static_assert(check_name_static<Obj, FieldType>()); - write_fun(&x, writer, &value); - } - - template<typename Obj, typename FieldType> - requires std::is_default_constructible_v<FieldType> - FieldType read(const Obj& x) const noexcept { assert_name<Obj, FieldType>(); return read_unchecked<Obj, FieldType>(x); } - - template<typename Obj, typename FieldType> - void read(const Obj& x, FieldType& value) const noexcept { assert_name<Obj, FieldType>(); read_unchecked<Obj, FieldType>(x, value); } - - template<typename Obj, typename FieldType> - void write(Obj& x, move_qualified<FieldType> value) const noexcept { assert_name<Obj, FieldType>(); write_unchecked<Obj, FieldType>(x, value); } -}; - template<typename Obj, typename Type> struct entity_field_base {}; template<typename Obj, typename Type, FieldReader<Obj, Type> R, FieldWriter<Obj, Type> W> diff --git a/entity/name-of.hpp b/entity/name-of.hpp new file mode 100644 index 00000000..592f07c1 --- /dev/null +++ b/entity/name-of.hpp @@ -0,0 +1,18 @@ +#pragma once +#include <Corrade/Containers/StringView.h> + +#if defined _MSC_VER +#define FM_PRETTY_FUNCTION __FUNCSIG__ +#else +#define FM_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#endif + +template<typename T> +static constexpr auto _name_of() { + using namespace Corrade::Containers; + using SVF = StringViewFlag; + constexpr const char* str = FM_PRETTY_FUNCTION; + return StringView { str, Implementation::strlen_(str), SVF::Global|SVF::NullTerminated }; +} + +template<typename T> constexpr inline Corrade::Containers::StringView name_of = _name_of<T>(); diff --git a/entity/util.hpp b/entity/util.hpp new file mode 100644 index 00000000..073745e9 --- /dev/null +++ b/entity/util.hpp @@ -0,0 +1,22 @@ +#pragma once +#include <type_traits> + +namespace Corrade::Containers { + +template<typename T> class BasicStringView; +using StringView = BasicStringView<const char>; + +} // namespace Corrade::Containers + +namespace floormat::entities { + +template<typename T, typename = void> struct pass_by_value : std::bool_constant<std::is_fundamental_v<T>> {}; +template<> struct pass_by_value<StringView> : std::true_type {}; +template<typename T> struct pass_by_value<T, std::enable_if_t<std::is_trivially_copy_constructible_v<T> && sizeof(T) <= sizeof(void*)>> : std::true_type {}; +template<typename T> constexpr inline bool pass_by_value_v = pass_by_value<T>::value; + +template<typename T> using const_qualified = std::conditional_t<pass_by_value_v<T>, T, const T&>; +template<typename T> using ref_qualified = std::conditional_t<pass_by_value_v<T>, T, T&>; +template<typename T> using move_qualified = std::conditional_t<pass_by_value_v<T>, T, T&&>; + +} // namespace floormat::entities diff --git a/test/entity.cpp b/test/entity.cpp index d8255e26..afec3f7c 100644 --- a/test/entity.cpp +++ b/test/entity.cpp @@ -1,6 +1,6 @@ #include "app.hpp" #include "compat/assert.hpp" -#include "src/entity.hpp" +#include "entity/entity.hpp" #include <tuple> using namespace floormat; |