Răsfoiți Sursa

test: ugly workaround for an ICE of VS2017 that fails to compile valid C++ code when combined with ENTT_API

Michele Caini 5 ani în urmă
părinte
comite
c8f0afb775
4 a modificat fișierele cu 24 adăugiri și 13 ștergeri
  1. 4 4
      src/entt/meta/factory.hpp
  2. 16 5
      src/entt/meta/meta.hpp
  3. 2 2
      src/entt/meta/resolve.hpp
  4. 2 2
      test/entt/meta/meta.cpp

+ 4 - 4
src/entt/meta/factory.hpp

@@ -393,11 +393,11 @@ public:
     auto type(const id_type id = type_info<Type>::id()) {
         auto * const node = internal::meta_info<Type>::resolve();
 
-        ENTT_ASSERT(!exists(id, *internal::meta_context::global));
-        ENTT_ASSERT(!exists(node, *internal::meta_context::global));
+        ENTT_ASSERT(!exists(id, *internal::meta_context::global()));
+        ENTT_ASSERT(!exists(node, *internal::meta_context::global()));
         node->id = id;
-        node->next = *internal::meta_context::global;
-        *internal::meta_context::global = node;
+        node->next = *internal::meta_context::global();
+        *internal::meta_context::global() = node;
 
         return meta_factory<Type, Type>{&node->prop};
     }

+ 16 - 5
src/entt/meta/meta.hpp

@@ -192,11 +192,22 @@ bool compare(const void *lhs, const void *rhs) {
 
 
 struct ENTT_API meta_context {
-    inline static meta_type_node *local = nullptr;
-    inline static meta_type_node **global = &local;
+    // we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
+    //     inline static meta_type_node *local = nullptr;
+    //     inline static meta_type_node **global = &local;
+
+    static meta_type_node * & local() ENTT_NOEXCEPT {
+        static meta_type_node *chain = nullptr;
+        return chain;
+    }
+
+    static meta_type_node ** & global() ENTT_NOEXCEPT {
+        static meta_type_node **chain = &local();
+        return chain;
+    }
 
     static void detach(const meta_type_node *node) ENTT_NOEXCEPT {
-        auto **it = global;
+        auto **it = global();
 
         while(*it && *it != node) {
             it = &(*it)->next;
@@ -261,11 +272,11 @@ struct meta_ctx {
      * @param other A valid context to which to bind.
      */
     static void bind(meta_ctx other) ENTT_NOEXCEPT {
-        internal::meta_context::global = other.ctx;
+        internal::meta_context::global() = other.ctx;
     }
 
 private:
-    internal::meta_type_node **ctx{&internal::meta_context::local};
+    internal::meta_type_node **ctx{&internal::meta_context::local()};
 };
 
 

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

@@ -27,7 +27,7 @@ inline meta_type resolve() ENTT_NOEXCEPT {
  */
 template<typename Op>
 void resolve(Op op) {
-    internal::visit<meta_type>(op, *internal::meta_context::global);
+    internal::visit<meta_type>(op, *internal::meta_context::global());
 }
 
 
@@ -41,7 +41,7 @@ template<typename Func>
 inline meta_type resolve_if(Func func) ENTT_NOEXCEPT {
     return internal::find_if([&func](const auto *curr) {
         return func(meta_type{curr});
-    }, *internal::meta_context::global);
+    }, *internal::meta_context::global());
 }
 
 

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

@@ -1879,7 +1879,7 @@ TEST_F(Meta, PropertiesAndCornerCases) {
 }
 
 TEST_F(Meta, Reset) {
-    ASSERT_NE(*entt::internal::meta_context::global, nullptr);
+    ASSERT_NE(*entt::internal::meta_context::global(), nullptr);
 
     entt::meta<char>().reset();
     entt::meta<concrete_type>().reset();
@@ -1909,7 +1909,7 @@ TEST_F(Meta, Reset) {
     ASSERT_FALSE(entt::resolve_id("another_abstract_type"_hs));
     ASSERT_FALSE(entt::resolve_id("concrete"_hs));
 
-    ASSERT_EQ(*entt::internal::meta_context::global, nullptr);
+    ASSERT_EQ(*entt::internal::meta_context::global(), nullptr);
 
     Meta::SetUpAfterUnregistration();
     entt::meta_any any{42.};