diff --git a/GeoModelCore/GeoModelKernel/CMakeLists.txt b/GeoModelCore/GeoModelKernel/CMakeLists.txt
index d49c84e643efde52771c3de5715696e88fbb311c..cd075745137fa0cddbd5193efd4ab401d86ae7a8 100644
--- a/GeoModelCore/GeoModelKernel/CMakeLists.txt
+++ b/GeoModelCore/GeoModelKernel/CMakeLists.txt
@@ -45,3 +45,10 @@ install(TARGETS GeoModelKernel
 install( FILES ${HEADERS}
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/GeoModelKernel
    COMPONENT Development )
+
+
+
+add_executable(testGeoIntrusivePtr tests/testGeoIntrusivePtr.cxx)
+target_link_libraries( testGeoIntrusivePtr GeoModelKernel)
+add_test(NAME testGeoIntrusivePtr
+         COMMAND testGeoIntrusivePtr)
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h
index 461aacfcc337467548c46857ce8737a693209e30..cef5d0577f9de8ef952cc8453c2b854665646646 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoIntrusivePtr.h
@@ -59,12 +59,22 @@ class GeoIntrusivePtr{
             if (m_ptr && m_ptr == other.get()) {
                 m_ptr->unref();
             } else {
-                reset(other.get());
+                m_ptr = other.get();
+            }
+            other.m_ptr = nullptr;
+            return *this;
+        }
+        template <typename GeoTypeGrp,
+                  typename = typename std::enable_if<!std::is_same<GeoType,GeoTypeGrp>::value, bool>>
+         GeoIntrusivePtr& operator=(GeoIntrusivePtr<GeoTypeGrp>&& other) {            
+            if (m_ptr && m_ptr == other.get()) {
+                m_ptr->unref();
+            } else {
+                m_ptr = other.get();
             }
             other.m_ptr = nullptr;
             return *this;
         }
-        
         /// Reset the pointer
         void reset(GeoType* ptr = nullptr) {
             if (m_ptr == ptr) return;
diff --git a/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx b/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..afc5e9586b791ddb224923eab5e28de32e3b8046
--- /dev/null
+++ b/GeoModelCore/GeoModelKernel/tests/testGeoIntrusivePtr.cxx
@@ -0,0 +1,67 @@
+// Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+
+
+#include <GeoModelKernel/GeoFullPhysVol.h>
+#include <GeoModelKernel/GeoPhysVol.h>
+#include <GeoModelKernel/GeoBox.h>
+#include <iostream>
+
+
+
+#define PRINT(OBJ)                                                                    \
+    std::cout<<__FILE__<<":"<<__LINE__<<" Print reference count of "<<(RCBase*)OBJ;   \
+    if (OBJ) std::cout<<" "<<typeid(*OBJ).name()<<" "<<OBJ->refCount();               \
+    std::cout<<std::endl;                                                             \
+
+
+#define CHECKCOUNT(OBJ, EXPECT)                                                                   \
+    if (OBJ->refCount() != EXPECT)  {                                                             \
+         PRINT(OBJ);                                                                              \
+         std::cerr<<__FILE__<<":"<<__LINE__<<" Expect a reference count of "<<EXPECT<<std::endl;  \
+         return EXIT_FAILURE;                                                                     \
+    }                                                                                             \
+    PRINT(OBJ);                                                                                   \
+    std::cout<<__FILE__<<":"<<__LINE__<<" Pass ref counter check of "<<EXPECT<<std::endl;         \
+
+int main(int argc, char *argv[]){
+    GeoMaterial* material = new GeoMaterial("Snow", 1.45);
+    GeoBox* uniCave = new GeoBox(100., 100., 100.);
+    /// Create the logical volume forklift which should increase the counters by one unit
+    GeoLogVol* logVol = new GeoLogVol("Forklift", uniCave, material);
+
+    CHECKCOUNT(material, 1);
+    CHECKCOUNT(uniCave, 1);
+
+    /// The logical volume should be also incremented by one unit then
+    GeoIntrusivePtr<GeoFullPhysVol> myPhysVol{new GeoFullPhysVol(logVol)};
+    CHECKCOUNT(myPhysVol, 1);
+    CHECKCOUNT(logVol, 1);    
+    /// Temporarilly create a new logical volume pointer
+    {
+        GeoIntrusivePtr<GeoLogVol> logInt{logVol};
+        CHECKCOUNT(logInt, 2);        
+    }
+    /// Another check that the logical volume is back to 1
+    CHECKCOUNT(logVol, 1);
+    {
+        /// Derived constructor from the mother
+        GeoIntrusivePtr<GeoVFullPhysVol> physVol2{myPhysVol};
+        CHECKCOUNT(physVol2, 2);
+       
+        /// Test move constructor
+        GeoIntrusivePtr<GeoVPhysVol> physVol3{std::move(physVol2)};
+        CHECKCOUNT(physVol3, 2);       
+        /// Test the copy assignment
+        GeoIntrusivePtr<GeoVPhysVol> physVol4{};
+        physVol4 = physVol3;
+        CHECKCOUNT(physVol4, 3);
+        /// Reset
+        physVol4.reset();
+        // We should be back to 2
+        CHECKCOUNT(physVol3, 2);
+        /// Move assignment
+        physVol4 = std::move(physVol3);
+        CHECKCOUNT(physVol4, 2);
+    }
+    return EXIT_SUCCESS;
+}