Browse Source

meta: policies

Michele Caini 6 years ago
parent
commit
6152387096
6 changed files with 93 additions and 45 deletions
  1. 1 2
      TODO
  2. 1 0
      src/entt/entt.hpp
  3. 49 37
      src/entt/meta/factory.hpp
  4. 2 1
      src/entt/meta/meta.hpp
  5. 35 0
      src/entt/meta/policy.hpp
  6. 5 5
      test/entt/meta/meta.cpp

+ 1 - 2
TODO

@@ -29,5 +29,4 @@ TODO
   - cloning all/part of the components are both required and a target entity on which to stomp your stuff could help
   - cloning all/part of the components are both required and a target entity on which to stomp your stuff could help
   - clone is just clone, creating new entity. But yeah, both "clone-all", and "clone-components"
   - clone is just clone, creating new entity. But yeah, both "clone-all", and "clone-components"
   - for "apply", again both All and Components, and maybe an enum of what kind of apply "dont overwrite, overwrite, add-only"
   - for "apply", again both All and Components, and maybe an enum of what kind of apply "dont overwrite, overwrite, add-only"
-* meta: copy on aliasing should make an actual copy of the value, not of the pointer (steal has a similar problem)
-* meta: almost always aliasing method
+* test meta policies

+ 1 - 0
src/entt/entt.hpp

@@ -21,6 +21,7 @@
 #include "locator/locator.hpp"
 #include "locator/locator.hpp"
 #include "meta/factory.hpp"
 #include "meta/factory.hpp"
 #include "meta/meta.hpp"
 #include "meta/meta.hpp"
+#include "meta/policy.hpp"
 #include "process/process.hpp"
 #include "process/process.hpp"
 #include "process/scheduler.hpp"
 #include "process/scheduler.hpp"
 #include "resource/cache.hpp"
 #include "resource/cache.hpp"

+ 49 - 37
src/entt/meta/factory.hpp

@@ -9,6 +9,7 @@
 #include <functional>
 #include <functional>
 #include <type_traits>
 #include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
+#include "policy.hpp"
 #include "meta.hpp"
 #include "meta.hpp"
 
 
 
 
@@ -146,12 +147,23 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
 }
 }
 
 
 
 
-template<typename Type, auto Data>
+template<typename Type, auto Data, typename Policy>
 meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index) {
 meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index) {
+    auto dispatch = []([[maybe_unused]] auto &&value) {
+        if constexpr(std::is_same_v<Policy, as_void_t>) {
+            return meta_any{std::in_place_type<void>};
+        } else if constexpr(std::is_same_v<Policy, as_alias_t>) {
+            return meta_any{as_alias, std::forward<decltype(value)>(value)};
+        } else {
+            static_assert(std::is_same_v<Policy, as_is_t>);
+            return meta_any{std::forward<decltype(value)>(value)};
+        }
+    };
+
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
         static_assert(std::is_invocable_v<decltype(Data), Type &>);
         static_assert(std::is_invocable_v<decltype(Data), Type &>);
         auto *clazz = handle.data<Type>();
         auto *clazz = handle.data<Type>();
-        return clazz ? std::invoke(Data, *clazz) : meta_any{};
+        return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
         static_assert(std::is_invocable_v<decltype(Data), Type *>);
         static_assert(std::is_invocable_v<decltype(Data), Type *>);
@@ -159,27 +171,38 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
 
 
         if constexpr(std::is_array_v<data_type>) {
         if constexpr(std::is_array_v<data_type>) {
             auto *idx = index.try_cast<std::size_t>();
             auto *idx = index.try_cast<std::size_t>();
-            return (clazz && idx) ? std::invoke(Data, clazz)[*idx] : meta_any{};
+            return (clazz && idx) ? dispatch(std::invoke(Data, clazz)[*idx]) : meta_any{};
         } else {
         } else {
-            return clazz ? std::invoke(Data, clazz) : meta_any{};
+            return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
         }
         }
     } else {
     } else {
         static_assert(std::is_pointer_v<decltype(Data)>);
         static_assert(std::is_pointer_v<decltype(Data)>);
 
 
         if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
         if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
             auto *idx = index.try_cast<std::size_t>();
             auto *idx = index.try_cast<std::size_t>();
-            return idx ? (*Data)[*idx] : meta_any{};
+            return idx ? dispatch((*Data)[*idx]) : meta_any{};
         } else {
         } else {
-            return *Data;
+            return dispatch(*Data);
         }
         }
     }
     }
 }
 }
 
 
 
 
-template<typename Type, auto Candidate, std::size_t... Indexes>
+template<typename Type, auto Candidate, typename Policy, std::size_t... Indexes>
 meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
 meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
     using helper_type = meta_function_helper_t<decltype(Candidate)>;
     using helper_type = meta_function_helper_t<decltype(Candidate)>;
-    meta_any any{};
+
+    auto dispatch = [](auto *... args) {
+        if constexpr(std::is_void_v<typename helper_type::return_type> || std::is_same_v<Policy, as_void_t>) {
+            std::invoke(Candidate, *args...);
+            return meta_any{std::in_place_type<void>};
+        } else if constexpr(std::is_same_v<Policy, as_alias_t>) {
+            return meta_any{as_alias, std::invoke(Candidate, *args...)};
+        } else {
+            static_assert(std::is_same_v<Policy, as_is_t>);
+            return meta_any{std::invoke(Candidate, *args...)};
+        }
+    };
 
 
     [[maybe_unused]] const auto direct = std::make_tuple([](meta_any *any, auto *instance) {
     [[maybe_unused]] const auto direct = std::make_tuple([](meta_any *any, auto *instance) {
         using arg_type = std::remove_reference_t<decltype(*instance)>;
         using arg_type = std::remove_reference_t<decltype(*instance)>;
@@ -192,28 +215,11 @@ meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_
     }(args+Indexes, (args+Indexes)->try_cast<std::tuple_element_t<Indexes, typename helper_type::args_type>>())...);
     }(args+Indexes, (args+Indexes)->try_cast<std::tuple_element_t<Indexes, typename helper_type::args_type>>())...);
 
 
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Candidate)>>) {
     if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Candidate)>>) {
-        if((std::get<Indexes>(direct) && ...)) {
-            if constexpr(std::is_void_v<typename helper_type::return_type>) {
-                std::invoke(Candidate, *std::get<Indexes>(direct)...);
-                any.emplace<void>();
-            } else {
-                any = std::invoke(Candidate, *std::get<Indexes>(direct)...);
-            }
-        }
+        return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
     } else {
     } else {
         auto *clazz = handle.data<Type>();
         auto *clazz = handle.data<Type>();
-
-        if(clazz && (std::get<Indexes>(direct) && ...)) {
-            if constexpr(std::is_void_v<typename helper_type::return_type>) {
-                std::invoke(Candidate, clazz, *std::get<Indexes>(direct)...);
-                any.emplace<void>();
-            } else {
-                any = std::invoke(Candidate, clazz, *std::get<Indexes>(direct)...);
-            }
-        }
+        return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
     }
     }
-
-    return any;
 }
 }
 
 
 
 
@@ -455,11 +461,12 @@ public:
      * type is a built-in one or a free function.
      * type is a built-in one or a free function.
      *
      *
      * @tparam Func The actual function to use as a constructor.
      * @tparam Func The actual function to use as a constructor.
+     * @tparam Policy Optional policy (no policy set by default).
      * @tparam Property Types of properties to assign to the meta data.
      * @tparam Property Types of properties to assign to the meta data.
      * @param property Properties to assign to the meta data.
      * @param property Properties to assign to the meta data.
      * @return A meta factory for the parent type.
      * @return A meta factory for the parent type.
      */
      */
-    template<auto Func, typename... Property>
+    template<auto Func, typename Policy = as_is_t, typename... Property>
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
     meta_factory ctor(Property &&... property) ENTT_NOEXCEPT {
         using helper_type = internal::meta_function_helper_t<decltype(Func)>;
         using helper_type = internal::meta_function_helper_t<decltype(Func)>;
         static_assert(std::is_same_v<typename helper_type::return_type, Type>);
         static_assert(std::is_same_v<typename helper_type::return_type, Type>);
@@ -473,7 +480,7 @@ public:
             helper_type::size,
             helper_type::size,
             &helper_type::arg,
             &helper_type::arg,
             [](meta_any * const any) {
             [](meta_any * const any) {
-                return internal::invoke<Type, Func>({}, any, std::make_index_sequence<helper_type::size>{});
+                return internal::invoke<Type, Func, Policy>({}, any, std::make_index_sequence<helper_type::size>{});
             },
             },
             []() ENTT_NOEXCEPT -> meta_ctor {
             []() ENTT_NOEXCEPT -> meta_ctor {
                 return &node;
                 return &node;
@@ -581,17 +588,20 @@ public:
      * reflected object will appear as if they were part of the type itself.
      * reflected object will appear as if they were part of the type itself.
      *
      *
      * @tparam Data The actual variable to attach to the meta type.
      * @tparam Data The actual variable to attach to the meta type.
+     * @tparam Policy Optional policy (no policy set by default).
      * @tparam Property Types of properties to assign to the meta data.
      * @tparam Property Types of properties to assign to the meta data.
      * @param identifier Unique identifier.
      * @param identifier Unique identifier.
      * @param property Properties to assign to the meta data.
      * @param property Properties to assign to the meta data.
      * @return A meta factory for the parent type.
      * @return A meta factory for the parent type.
      */
      */
-    template<auto Data, typename... Property>
+    template<auto Data, typename Policy = as_is_t, typename... Property>
     meta_factory data(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
     meta_factory data(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
         auto * const type = internal::meta_info<Type>::resolve();
         auto * const type = internal::meta_info<Type>::resolve();
         internal::meta_data_node *curr = nullptr;
         internal::meta_data_node *curr = nullptr;
 
 
         if constexpr(std::is_same_v<Type, decltype(Data)>) {
         if constexpr(std::is_same_v<Type, decltype(Data)>) {
+            static_assert(std::is_same_v<Policy, as_is_t>);
+
             static internal::meta_data_node node{
             static internal::meta_data_node node{
                 &internal::meta_info<Type>::template data<Data>,
                 &internal::meta_info<Type>::template data<Data>,
                 {},
                 {},
@@ -623,7 +633,7 @@ public:
                 !std::is_member_object_pointer_v<decltype(Data)>,
                 !std::is_member_object_pointer_v<decltype(Data)>,
                 &internal::meta_info<data_type>::resolve,
                 &internal::meta_info<data_type>::resolve,
                 &internal::setter<std::is_const_v<data_type>, Type, Data>,
                 &internal::setter<std::is_const_v<data_type>, Type, Data>,
-                &internal::getter<Type, Data>,
+                &internal::getter<Type, Data, Policy>,
                 []() ENTT_NOEXCEPT -> meta_data {
                 []() ENTT_NOEXCEPT -> meta_data {
                     return &node;
                     return &node;
                 }
                 }
@@ -645,7 +655,7 @@ public:
                 !std::is_member_object_pointer_v<decltype(Data)>,
                 !std::is_member_object_pointer_v<decltype(Data)>,
                 &internal::meta_info<data_type>::resolve,
                 &internal::meta_info<data_type>::resolve,
                 &internal::setter<std::is_const_v<data_type>, Type, Data>,
                 &internal::setter<std::is_const_v<data_type>, Type, Data>,
-                &internal::getter<Type, Data>,
+                &internal::getter<Type, Data, Policy>,
                 []() ENTT_NOEXCEPT -> meta_data {
                 []() ENTT_NOEXCEPT -> meta_data {
                     return &node;
                     return &node;
                 }
                 }
@@ -681,12 +691,13 @@ public:
      *
      *
      * @tparam Setter The actual function to use as a setter.
      * @tparam Setter The actual function to use as a setter.
      * @tparam Getter The actual function to use as a getter.
      * @tparam Getter The actual function to use as a getter.
+     * @tparam Policy Optional policy (no policy set by default).
      * @tparam Property Types of properties to assign to the meta data.
      * @tparam Property Types of properties to assign to the meta data.
      * @param identifier Unique identifier.
      * @param identifier Unique identifier.
      * @param property Properties to assign to the meta data.
      * @param property Properties to assign to the meta data.
      * @return A meta factory for the parent type.
      * @return A meta factory for the parent type.
      */
      */
-    template<auto Setter, auto Getter, typename... Property>
+    template<auto Setter, auto Getter, typename Policy = as_is_t, typename... Property>
     meta_factory data(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
     meta_factory data(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
         using owner_type = std::tuple<std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>;
         using owner_type = std::tuple<std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>;
         using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
         using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
@@ -703,7 +714,7 @@ public:
             false,
             false,
             &internal::meta_info<underlying_type>::resolve,
             &internal::meta_info<underlying_type>::resolve,
             &internal::setter<false, Type, Setter>,
             &internal::setter<false, Type, Setter>,
-            &internal::getter<Type, Getter>,
+            &internal::getter<Type, Getter, Policy>,
             []() ENTT_NOEXCEPT -> meta_data {
             []() ENTT_NOEXCEPT -> meta_data {
                 return &node;
                 return &node;
             }
             }
@@ -729,12 +740,13 @@ public:
      * reflected object will appear as if they were part of the type itself.
      * reflected object will appear as if they were part of the type itself.
      *
      *
      * @tparam Candidate The actual function to attach to the meta type.
      * @tparam Candidate The actual function to attach to the meta type.
+     * @tparam Policy Optional policy (no policy set by default).
      * @tparam Property Types of properties to assign to the meta function.
      * @tparam Property Types of properties to assign to the meta function.
      * @param identifier Unique identifier.
      * @param identifier Unique identifier.
      * @param property Properties to assign to the meta function.
      * @param property Properties to assign to the meta function.
      * @return A meta factory for the parent type.
      * @return A meta factory for the parent type.
      */
      */
-    template<auto Candidate, typename... Property>
+    template<auto Candidate, typename Policy = as_is_t, typename... Property>
     meta_factory func(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
     meta_factory func(const ENTT_ID_TYPE identifier, Property &&... property) ENTT_NOEXCEPT {
         using owner_type = std::integral_constant<decltype(Candidate), Candidate>;
         using owner_type = std::integral_constant<decltype(Candidate), Candidate>;
         using helper_type = internal::meta_function_helper_t<decltype(Candidate)>;
         using helper_type = internal::meta_function_helper_t<decltype(Candidate)>;
@@ -749,10 +761,10 @@ public:
             helper_type::size,
             helper_type::size,
             helper_type::is_const,
             helper_type::is_const,
             !std::is_member_function_pointer_v<decltype(Candidate)>,
             !std::is_member_function_pointer_v<decltype(Candidate)>,
-            &internal::meta_info<typename helper_type::return_type>::resolve,
+            &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
             &helper_type::arg,
             &helper_type::arg,
             [](meta_handle handle, meta_any *any) {
             [](meta_handle handle, meta_any *any) {
-                return internal::invoke<Type, Candidate>(handle, any, std::make_index_sequence<helper_type::size>{});
+                return internal::invoke<Type, Candidate, Policy>(handle, any, std::make_index_sequence<helper_type::size>{});
             },
             },
             []() ENTT_NOEXCEPT -> meta_func {
             []() ENTT_NOEXCEPT -> meta_func {
                 return &node;
                 return &node;

+ 2 - 1
src/entt/meta/meta.hpp

@@ -9,6 +9,7 @@
 #include <utility>
 #include <utility>
 #include <type_traits>
 #include <type_traits>
 #include "../config/config.h"
 #include "../config/config.h"
+#include "policy.hpp"
 
 
 
 
 namespace entt {
 namespace entt {
@@ -415,7 +416,7 @@ public:
      * @param type An instance of an object to use to initialize the container.
      * @param type An instance of an object to use to initialize the container.
      */
      */
     template<typename Type>
     template<typename Type>
-    explicit meta_any(std::in_place_t, Type &type)
+    explicit meta_any(as_alias_t, Type &type)
         : meta_any{}
         : meta_any{}
     {
     {
         node = internal::meta_info<Type>::resolve();
         node = internal::meta_info<Type>::resolve();

+ 35 - 0
src/entt/meta/policy.hpp

@@ -0,0 +1,35 @@
+#ifndef ENTT_META_POLICY_HPP
+#define ENTT_META_POLICY_HPP
+
+
+namespace entt {
+
+
+/*! @brief Empty class type used for disambiguation. */
+struct as_is_t {};
+
+
+/*! @brief Disambiguation tag. */
+constexpr as_is_t as_is;
+
+
+/*! @brief Empty class type used for disambiguation. */
+struct as_alias_t {};
+
+
+/*! @brief Disambiguation tag. */
+constexpr as_alias_t as_alias;
+
+
+/*! @brief Empty class type used for disambiguation. */
+struct as_void_t {};
+
+
+/*! @brief Disambiguation tag. */
+constexpr as_void_t as_void;
+
+
+}
+
+
+#endif // ENTT_META_POLICY_HPP

+ 5 - 5
test/entt/meta/meta.cpp

@@ -288,7 +288,7 @@ TEST_F(Meta, MetaAnySBOInPlaceTypeConstruction) {
 TEST_F(Meta, MetaAnySBOInPlaceConstruction) {
 TEST_F(Meta, MetaAnySBOInPlaceConstruction) {
     int value = 3;
     int value = 3;
     int other = 42;
     int other = 42;
-    entt::meta_any any{std::in_place, value};
+    entt::meta_any any{entt::as_alias, value};
 
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.try_cast<std::size_t>());
     ASSERT_FALSE(any.try_cast<std::size_t>());
@@ -297,8 +297,8 @@ TEST_F(Meta, MetaAnySBOInPlaceConstruction) {
     ASSERT_EQ(std::as_const(any).cast<int>(), 3);
     ASSERT_EQ(std::as_const(any).cast<int>(), 3);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_NE(std::as_const(any).data(), nullptr);
     ASSERT_NE(std::as_const(any).data(), nullptr);
-    ASSERT_EQ(any, (entt::meta_any{std::in_place, value}));
-    ASSERT_NE(any, (entt::meta_any{std::in_place, other}));
+    ASSERT_EQ(any, (entt::meta_any{entt::as_alias, value}));
+    ASSERT_NE(any, (entt::meta_any{entt::as_alias, other}));
     ASSERT_NE(any, entt::meta_any{42});
     ASSERT_NE(any, entt::meta_any{42});
     ASSERT_EQ(entt::meta_any{3}, any);
     ASSERT_EQ(entt::meta_any{3}, any);
 }
 }
@@ -395,7 +395,7 @@ TEST_F(Meta, MetaAnyNoSBOInPlaceTypeConstruction) {
 TEST_F(Meta, MetaAnyNoSBOInPlaceConstruction) {
 TEST_F(Meta, MetaAnyNoSBOInPlaceConstruction) {
     int value = 3;
     int value = 3;
     fat_type instance{&value};
     fat_type instance{&value};
-    entt::meta_any any{std::in_place, instance};
+    entt::meta_any any{entt::as_alias, instance};
 
 
     ASSERT_TRUE(any);
     ASSERT_TRUE(any);
     ASSERT_FALSE(any.try_cast<std::size_t>());
     ASSERT_FALSE(any.try_cast<std::size_t>());
@@ -404,7 +404,7 @@ TEST_F(Meta, MetaAnyNoSBOInPlaceConstruction) {
     ASSERT_EQ(std::as_const(any).cast<fat_type>(), instance);
     ASSERT_EQ(std::as_const(any).cast<fat_type>(), instance);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_NE(any.data(), nullptr);
     ASSERT_NE(std::as_const(any).data(), nullptr);
     ASSERT_NE(std::as_const(any).data(), nullptr);
-    ASSERT_EQ(any, (entt::meta_any{std::in_place, instance}));
+    ASSERT_EQ(any, (entt::meta_any{entt::as_alias, instance}));
     ASSERT_EQ(any, entt::meta_any{instance});
     ASSERT_EQ(any, entt::meta_any{instance});
     ASSERT_NE(entt::meta_any{fat_type{}}, any);
     ASSERT_NE(entt::meta_any{fat_type{}}, any);
 }
 }