Просмотр исходного кода

any/poly: review align parameter and default values (close #676)

Michele Caini 5 лет назад
Родитель
Сommit
dc4279a2d0
4 измененных файлов с 35 добавлено и 34 удалено
  1. 17 20
      src/entt/core/any.hpp
  2. 2 1
      src/entt/core/fwd.hpp
  3. 4 1
      src/entt/poly/fwd.hpp
  4. 12 12
      src/entt/poly/poly.hpp

+ 17 - 20
src/entt/core/any.hpp

@@ -21,14 +21,11 @@ namespace entt {
  * @tparam Len Size of the storage reserved for the small buffer optimization.
  * @tparam Align Optional alignment requirement.
  */
-template<std::size_t Len, std::size_t... Align>
+template<std::size_t Len, std::size_t Align>
 class basic_any {
-    static_assert(sizeof...(Align) == 0u || Len);
-
     enum class operation { COPY, MOVE, DTOR, COMP, ADDR, CADDR, REF, CREF, TYPE };
 
-    // cannot use std::aligned_storage_t with parameter packs because of an issue of msvc
-    using storage_type = typename std::aligned_storage<Len + !Len, Align...>::type;
+    using storage_type = std::aligned_storage_t<Len + !Len, Align>;
     using vtable_type = const void *(const operation, const basic_any &, const void *);
 
     template<typename Type>
@@ -341,13 +338,13 @@ private:
 /**
  * @brief Checks if two wrappers differ in their content.
  * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
+ * @tparam Align Alignment requirement.
  * @param lhs A wrapper, either empty or not.
  * @param rhs A wrapper, either empty or not.
  * @return True if the two wrappers differ in their content, false otherwise.
  */
-template<std::size_t Len, std::size_t... Align>
-[[nodiscard]] inline bool operator!=(const basic_any<Len, Align...> &lhs, const basic_any<Len, Align...> &rhs) ENTT_NOEXCEPT {
+template<std::size_t Len, std::size_t Align>
+[[nodiscard]] inline bool operator!=(const basic_any<Len, Align> &lhs, const basic_any<Len, Align> &rhs) ENTT_NOEXCEPT {
     return !(lhs == rhs);
 }
 
@@ -356,12 +353,12 @@ template<std::size_t Len, std::size_t... Align>
  * @brief Performs type-safe access to the contained object.
  * @tparam Type Type to which conversion is required.
  * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
+ * @tparam Align Alignment requirement.
  * @param data Target any object.
  * @return The element converted to the requested type.
  */
-template<typename Type, std::size_t Len, std::size_t... Align>
-Type any_cast(const basic_any<Len, Align...> &data) ENTT_NOEXCEPT {
+template<typename Type, std::size_t Len, std::size_t Align>
+Type any_cast(const basic_any<Len, Align> &data) ENTT_NOEXCEPT {
     const auto * const instance = any_cast<std::remove_reference_t<Type>>(&data);
     ENTT_ASSERT(instance);
     return static_cast<Type>(*instance);
@@ -369,8 +366,8 @@ Type any_cast(const basic_any<Len, Align...> &data) ENTT_NOEXCEPT {
 
 
 /*! @copydoc any_cast */
-template<typename Type, std::size_t Len, std::size_t... Align>
-Type any_cast(basic_any<Len, Align...> &data) ENTT_NOEXCEPT {
+template<typename Type, std::size_t Len, std::size_t Align>
+Type any_cast(basic_any<Len, Align> &data) ENTT_NOEXCEPT {
     // forces const on non-reference types to make them work also with wrappers for const references
     auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
     ENTT_ASSERT(instance);
@@ -379,8 +376,8 @@ Type any_cast(basic_any<Len, Align...> &data) ENTT_NOEXCEPT {
 
 
 /*! @copydoc any_cast */
-template<typename Type, std::size_t Len, std::size_t... Align>
-Type any_cast(basic_any<Len, Align...> &&data) ENTT_NOEXCEPT {
+template<typename Type, std::size_t Len, std::size_t Align>
+Type any_cast(basic_any<Len, Align> &&data) ENTT_NOEXCEPT {
     // forces const on non-reference types to make them work also with wrappers for const references
     auto * const instance = any_cast<std::conditional_t<std::is_reference_v<Type>, std::remove_reference_t<Type>, const Type>>(&data);
     ENTT_ASSERT(instance);
@@ -389,17 +386,17 @@ Type any_cast(basic_any<Len, Align...> &&data) ENTT_NOEXCEPT {
 
 
 /*! @copydoc any_cast */
-template<typename Type, std::size_t Len, std::size_t... Align>
-const Type * any_cast(const basic_any<Len, Align...> *data) ENTT_NOEXCEPT {
+template<typename Type, std::size_t Len, std::size_t Align>
+const Type * any_cast(const basic_any<Len, Align> *data) ENTT_NOEXCEPT {
     return (data->type() == type_id<Type>() ? static_cast<const Type *>(data->data()) : nullptr);
 }
 
 
 /*! @copydoc any_cast */
-template<typename Type, std::size_t Len, std::size_t... Align>
-Type * any_cast(basic_any<Len, Align...> *data) ENTT_NOEXCEPT {
+template<typename Type, std::size_t Len, std::size_t Align>
+Type * any_cast(basic_any<Len, Align> *data) ENTT_NOEXCEPT {
     // last attempt to make wrappers for const references return their values
-    return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align...>, Type> *>(data)->data()) : nullptr);
+    return (data->type() == type_id<Type>() ? static_cast<Type *>(static_cast<constness_as_t<basic_any<Len, Align>, Type> *>(data)->data()) : nullptr);
 }
 
 

+ 2 - 1
src/entt/core/fwd.hpp

@@ -2,13 +2,14 @@
 #define ENTT_CORE_FWD_HPP
 
 
+#include <type_traits>
 #include "../config/config.h"
 
 
 namespace entt {
 
 
-template<std::size_t, std::size_t...>
+template<std::size_t Len, std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
 class basic_any;
 
 

+ 4 - 1
src/entt/poly/fwd.hpp

@@ -2,10 +2,13 @@
 #define ENTT_POLY_FWD_HPP
 
 
+#include <type_traits>
+
+
 namespace entt {
 
 
-template<typename, std::size_t, std::size_t...>
+template<typename, std::size_t Len, std::size_t = alignof(typename std::aligned_storage_t<Len + !Len>)>
 class basic_poly;
 
 

+ 12 - 12
src/entt/poly/poly.hpp

@@ -46,26 +46,26 @@ struct poly_inspector {
  * @brief Static virtual table factory.
  * @tparam Concept Concept descriptor.
  * @tparam Len Size of the storage reserved for the small buffer optimization.
- * @tparam Align Optional alignment requirement.
+ * @tparam Align Alignment requirement.
  */
-template<typename Concept, std::size_t Len, std::size_t... Align>
+template<typename Concept, std::size_t Len, std::size_t Align>
 class poly_vtable {
     using inspector = typename Concept::template type<poly_inspector>;
 
     template<typename Ret, typename... Args>
-    static auto vtable_entry(Ret(*)(inspector &, Args...)) -> Ret(*)(basic_any<Len, Align...> &, Args...);
+    static auto vtable_entry(Ret(*)(inspector &, Args...)) -> Ret(*)(basic_any<Len, Align> &, Args...);
 
     template<typename Ret, typename... Args>
-    static auto vtable_entry(Ret(*)(const inspector &, Args...)) -> Ret(*)(const basic_any<Len, Align...> &, Args...);
+    static auto vtable_entry(Ret(*)(const inspector &, Args...)) -> Ret(*)(const basic_any<Len, Align> &, Args...);
 
     template<typename Ret, typename... Args>
-    static auto vtable_entry(Ret(*)(Args...)) -> Ret(*)(const basic_any<Len, Align...> &, Args...);
+    static auto vtable_entry(Ret(*)(Args...)) -> Ret(*)(const basic_any<Len, Align> &, Args...);
 
     template<typename Ret, typename... Args>
-    static auto vtable_entry(Ret(inspector:: *)(Args...)) -> Ret(*)(basic_any<Len, Align...> &, Args...);
+    static auto vtable_entry(Ret(inspector:: *)(Args...)) -> Ret(*)(basic_any<Len, Align> &, Args...);
 
     template<typename Ret, typename... Args>
-    static auto vtable_entry(Ret(inspector:: *)(Args...) const) -> Ret(*)(const basic_any<Len, Align...> &, Args...);
+    static auto vtable_entry(Ret(inspector:: *)(Args...) const) -> Ret(*)(const basic_any<Len, Align> &, Args...);
 
     template<auto... Candidate>
     static auto make_vtable(value_list<Candidate...>)
@@ -177,12 +177,12 @@ decltype(auto) poly_call(Poly &&self, Args &&... args) {
  * @tparam Len Size of the storage reserved for the small buffer optimization.
  * @tparam Align Optional alignment requirement.
  */
-template<typename Concept, std::size_t Len, std::size_t... Align>
-class basic_poly: private Concept::template type<poly_base<basic_poly<Concept, Len, Align...>>> {
+template<typename Concept, std::size_t Len, std::size_t Align>
+class basic_poly: private Concept::template type<poly_base<basic_poly<Concept, Len, Align>>> {
     /*! @brief A poly base is allowed to snoop into a poly object. */
     friend struct poly_base<basic_poly>;
 
-    using vtable_type = typename poly_vtable<Concept, Len, Align...>::type;
+    using vtable_type = typename poly_vtable<Concept, Len, Align>::type;
 
 public:
     /*! @brief Concept type. */
@@ -203,7 +203,7 @@ public:
     template<typename Type, typename... Args>
     explicit basic_poly(std::in_place_type_t<Type>, Args &&... args)
         : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
-          vtable{poly_vtable<Concept, Len, Align...>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>()}
+          vtable{poly_vtable<Concept, Len, Align>::template instance<std::remove_const_t<std::remove_reference_t<Type>>>()}
     {}
 
     /**
@@ -340,7 +340,7 @@ public:
     }
 
 private:
-    basic_any<Len, Align...> storage;
+    basic_any<Len, Align> storage;
     const vtable_type *vtable;
 };