0027563: Foundation Classes, opencascade::handle - make operator*() consistent with...
[occt.git] / src / Standard / Standard_Handle.hxx
index 23b075b..f4fc154 100644 (file)
@@ -69,6 +69,12 @@ namespace opencascade {
       BeginScope();
     }
 
+    //! Move constructor
+    handle (handle&& theHandle) : entity(theHandle.entity)
+    {
+      theHandle.entity = 0;
+    }
+
     //! Destructor
     ~handle ()
     {
@@ -104,20 +110,22 @@ namespace opencascade {
       return *this;
     }
 
-    //! STL-like cast to pointer to referred object
-    const T* get () const { return static_cast<const T*>(this->entity); }
+    //! Move operator
+    handle& operator= (handle&& theHandle)
+    {
+      std::swap (this->entity, theHandle.entity);
+      return *this;
+    }
 
-    //! STL-like cast to pointer to referred object
-    T* get () { return static_cast<T*>(this->entity); }
+    //! STL-like cast to pointer to referred object (note non-const).
+    //! @sa std::shared_ptr::get()
+    T* get() const { return static_cast<T*>(this->entity); }
 
     //! Member access operator (note non-const)
     T* operator-> () const { return static_cast<T*>(this->entity); }
 
-    //! Dereferencing operator
-    T& operator* () { return *get(); }
-
-    //! Const dereferencing operator
-    const T& operator*() const { return *get(); }
+    //! Dereferencing operator (note non-const)
+    T& operator* () const { return *get(); }
 
     //! Check for equality
     template <class T2>
@@ -168,16 +176,34 @@ namespace opencascade {
       return get() < theHandle.get();
     }
 
-    //! Down casting operator
+    //! Down casting operator from handle to base type
+    template <class T2>
+    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type
+      DownCast (const handle<T2>& theObject)
+    {
+      return handle (dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
+    }
+
+    //! Down casting operator from pointer to base type
+    template <class T2>
+    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
+      DownCast (const T2* thePtr)
+    {
+      return handle (dynamic_cast<T*>(const_cast<T2*>(thePtr)));
+    }
+
+    //! For compatibility, define down casting operator from non-base type, as deprecated
     template <class T2>
-    static handle DownCast (const handle<T2>& theObject)
+    Standard_DEPRECATED("down-casting from object of the same or unrelated type is meaningless")
+    static handle DownCast (const handle<T2>& theObject, typename std::enable_if<!is_base_but_not_same<T2, T>::value, void*>::type = 0)
     {
       return handle (dynamic_cast<T*>(const_cast<T2*>(theObject.get())));
     }
 
-    //! Down casting operator
+    //! For compatibility, define down casting operator from non-base type, as deprecated
     template <class T2>
-    static handle DownCast (const T2* thePtr)
+    Standard_DEPRECATED("down-casting from object of the same or unrelated type is meaningless")
+    static handle DownCast (const T2* thePtr, typename std::enable_if<!is_base_but_not_same<T2, T>::value, void*>::type = 0)
     {
       return handle (dynamic_cast<T*>(const_cast<T2*>(thePtr)));
     }
@@ -220,6 +246,14 @@ namespace opencascade {
       BeginScope();
     }
 
+    //! Generalized move constructor
+    template <class T2, typename = typename std::enable_if <is_base_but_not_same <T, T2>::value>::type>
+    handle (handle<T2>&& theHandle)
+      : entity(theHandle.entity)
+    {
+      theHandle.entity = 0;
+    }
+
     //! Generalized assignment operator
     template <class T2, typename = typename std::enable_if <is_base_but_not_same <T, T2>::value>::type>
     handle operator = (const handle<T2>& theHandle)
@@ -228,6 +262,14 @@ namespace opencascade {
       return *this;
     }
 
+    //! Generalized move operator
+    template <class T2, typename = typename std::enable_if <is_base_but_not_same <T, T2>::value>::type>
+    handle& operator= (handle<T2>&& theHandle)
+    {
+      std::swap (this->entity, theHandle.entity);
+      return *this;
+    }
+
 #else
 
     //! Upcast to const reference to base type.
@@ -260,6 +302,14 @@ namespace opencascade {
       BeginScope();
     }
 
+    //! Generalized move constructor
+    template <class T2>
+    handle (handle<T2>&& theHandle, typename std::enable_if <is_base_but_not_same <T, T2>::value>::type* = nullptr)
+      : entity(theHandle.entity)
+    {
+      theHandle.entity = 0;
+    }
+
     //! Generalized assignment operator.
     template <class T2>
     handle operator = (const handle<T2>& theHandle)
@@ -270,6 +320,16 @@ namespace opencascade {
       return *this;
     }
 
+    //! Generalized move operator
+    template <class T2>
+    handle& operator= (handle<T2>&& theHandle)
+    {
+      std::enable_if <is_base_but_not_same <T, T2>::value, void*>::type aTypeCheckHelperVar;
+      (void)aTypeCheckHelperVar;
+      std::swap (this->entity, theHandle.entity);
+      return *this;
+    }
+
 #else
 
     //! Upcast to const reference to base type.
@@ -344,8 +404,25 @@ inline Standard_Integer HashCode (const Handle(T)& theHandle, const Standard_Int
   return ::HashCode (const_cast<Standard_Address>(static_cast<const void*>(theHandle.get())), theUpper);
 }
 
-//! For compatibility with previous versions of OCCT, defines typedef opencascade::handle<Class> Handle(Class)
+//! For compatibility with previous versions of OCCT, define Handle_Class alias for opencascade::handle<Class>.
+#if (defined(_MSC_VER) && _MSC_VER >= 1800) 
+//! For Visual Studio 2013+, define Handle_Class as non-template class to allow exporting this type in C++/CLI.
+#define DEFINE_STANDARD_HANDLECLASS(C1,C2,BC) class C1; class Handle_##C1 : public Handle(C1) \
+{ \
+public: \
+  Handle_##C1() {} \
+  Handle_##C1(Handle(C1)&& theHandle) : Handle(C1)(theHandle) {} \
+  template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> \
+  inline Handle_##C1(const opencascade::handle<T2>& theOther) : Handle(C1)(theOther) {} \
+  template <class T2, typename = typename std::enable_if <std::is_base_of <C1,T2>::value>::type> \
+  inline Handle_##C1(const T2* theOther) : Handle(C1)(theOther) {} \
+  template<typename T> inline Handle_##C1& operator=(T theOther) { Handle(C1)::operator=(theOther); return *this; } \
+};
+#else
+//! For other compilers, use simple typedef
 #define DEFINE_STANDARD_HANDLECLASS(C1,C2,BC) class C1; typedef Handle(C1) Handle_##C1;
+#endif
+
 #define DEFINE_STANDARD_HANDLE(C1,C2) DEFINE_STANDARD_HANDLECLASS(C1,C2,Standard_Transient)
 #define DEFINE_STANDARD_PHANDLE(C1,C2) DEFINE_STANDARD_HANDLECLASS(C1,C2,Standard_Persistent)