Michele Caini 5 лет назад
Родитель
Сommit
7967c6dfc8
4 измененных файлов с 46 добавлено и 3 удалено
  1. 13 0
      docs/md/core.md
  2. 25 1
      src/entt/core/type_traits.hpp
  3. 1 2
      src/entt/entity/storage.hpp
  4. 7 0
      test/entt/core/type_traits.cpp

+ 13 - 0
docs/md/core.md

@@ -17,6 +17,7 @@
   * [Type info](#type-info)
     * [Almost unique identifiers](#almost-unique-identifiers)
   * [Type traits](#type-traits)
+    * [Size of](#size-of)
     * [Member class type](#member-class-type)
     * [Integral constant](#integral-constant)
     * [Tag](#tag)
@@ -376,6 +377,18 @@ This list **is not** exhaustive and contains only some of the most useful
 classes. Refer to the inline documentation for more information on the features
 offered by this module.
 
+### Size of
+
+The standard operator `sizeof` complains when users provide it for example with
+function or incomplete types. On the other hand, it's guaranteed that its result
+is always nonzero, even if applied to an empty class type.<br/>
+This small class combines the two and offers an alternative to `sizeof` that
+works under all circumstances, returning zero if the type isn't supported:
+
+```cpp
+const auto size = entt::size_of_v<void>;
+```
+
 ### Member class type
 
 The `auto` template parameter introduced with C++17 made it possible to simplify

+ 25 - 1
src/entt/core/type_traits.hpp

@@ -12,6 +12,30 @@
 namespace entt {
 
 
+/**
+ * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains.
+ * @tparam Type The type of which to return the size.
+ * @tparam The size of the type if `sizeof` accepts it, 0 otherwise.
+ */
+template<typename Type, typename = void>
+struct size_of: std::integral_constant<std::size_t, 0u> {};
+
+
+/*! @copydoc size_of */
+template<typename Type>
+struct size_of<Type, std::void_t<decltype(sizeof(Type))>>
+    : std::integral_constant<std::size_t, sizeof(Type)>
+{};
+
+
+/**
+* @brief Helper variable template.
+* @tparam Type The type of which to return the size.
+*/
+template<class Type>
+inline constexpr auto size_of_v = size_of<Type>::value;
+
+
 /**
  * @brief Using declaration to be used to _repeat_ the same type a number of
  * times equal to the size of a given parameter pack.
@@ -215,7 +239,7 @@ inline constexpr auto type_list_contains_v = type_list_contains<List, Type>::val
  * equality comparable, false otherwise.
  * @tparam Type Potentially equality comparable type.
  */
-template<typename Type, typename = std::void_t<>>
+template<typename Type, typename = void>
 struct is_equality_comparable: std::false_type {};
 
 

+ 1 - 2
src/entt/entity/storage.hpp

@@ -45,7 +45,7 @@ namespace entt {
  * @tparam Entity A valid entity type (see entt_traits for more details).
  * @tparam Type Type of objects assigned to the entities.
  */
-template<typename Entity, typename Type, typename = std::void_t<>>
+template<typename Entity, typename Type, typename = void>
 class storage: public sparse_set<Entity> {
     static_assert(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>, "The managed type must be at least move constructible and assignable");
 
@@ -171,7 +171,6 @@ public:
     /*! @brief Constant reverse iterator type. */
     using const_reverse_iterator = const Type *;
 
-
     /**
      * @brief Increases the capacity of a storage.
      *

+ 7 - 0
test/entt/core/type_traits.cpp

@@ -9,6 +9,13 @@
 #include <entt/core/hashed_string.hpp>
 #include <entt/core/type_traits.hpp>
 
+TEST(TypeTraits, SizeOf) {
+    static_assert(entt::size_of_v<void> == 0u);
+    static_assert(entt::size_of_v<char> == sizeof(char));
+    static_assert(entt::size_of_v<int[]> == 0u);
+    static_assert(entt::size_of_v<int[3]> == sizeof(int[3]));
+}
+
 TEST(TypeTraits, UnpackAsType) {
     ASSERT_EQ([](auto &&... args) {
         return [](entt::unpack_as_t<int, decltype(args)>... value) {