From e2d0d129170ff39f0ed802cf3def3146f609529e Mon Sep 17 00:00:00 2001
From: Robert Bradshaw <robertwb@gmail.com>
Date: Tue, 31 Jul 2018 22:51:05 -0700
Subject: [PATCH] Add C++11 smart pointer casts.

---
 Cython/Includes/libcpp/memory.pxd |  6 ++++++
 tests/run/cpp_smart_ptr.pyx       | 17 +++++++++++++++--
 tests/run/cpp_smart_ptr_helper.h  |  2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/Cython/Includes/libcpp/memory.pxd b/Cython/Includes/libcpp/memory.pxd
index b300dda32..2151c1ec7 100644
--- a/Cython/Includes/libcpp/memory.pxd
+++ b/Cython/Includes/libcpp/memory.pxd
@@ -107,3 +107,9 @@ cdef extern from "<memory>" namespace "std" nogil:
 
     # Temporaries used for exception handling break generated code
     unique_ptr[T] make_unique[T](...) # except +
+
+    # No checking on the compatibility of T and U.
+    cdef shared_ptr[T] static_pointer_cast[T, U](const shared_ptr[U]&)
+    cdef shared_ptr[T] dynamic_pointer_cast[T, U](const shared_ptr[U]&)
+    cdef shared_ptr[T] const_pointer_cast[T, U](const shared_ptr[U]&)
+    cdef shared_ptr[T] reinterpret_pointer_cast[T, U](const shared_ptr[U]&)
diff --git a/tests/run/cpp_smart_ptr.pyx b/tests/run/cpp_smart_ptr.pyx
index 7822e287b..e6f2a53cc 100644
--- a/tests/run/cpp_smart_ptr.pyx
+++ b/tests/run/cpp_smart_ptr.pyx
@@ -2,7 +2,7 @@
 # tag: cpp, werror, cpp11
 # distutils: extra_compile_args=-std=c++0x
 
-from libcpp.memory cimport unique_ptr, shared_ptr, default_delete
+from libcpp.memory cimport unique_ptr, shared_ptr, default_delete, dynamic_pointer_cast
 from libcpp cimport nullptr
 
 cdef extern from "cpp_smart_ptr_helper.h":
@@ -71,7 +71,8 @@ def test_const_shared_ptr():
 
 
 cdef cppclass A:
-    pass
+    void some_method():  # Force this to be a polymorphic class for dynamic cast.
+        pass
 
 cdef cppclass B(A):
     pass
@@ -80,3 +81,15 @@ cdef cppclass C(B):
     pass
 
 cdef shared_ptr[A] holding_subclass = shared_ptr[A](new C())
+
+def test_dynamic_pointer_cast():
+    """
+    >>> test_dynamic_pointer_cast()
+    """
+    cdef shared_ptr[B] b = shared_ptr[B](new B())
+    cdef shared_ptr[A] a = dynamic_pointer_cast[A, B](b)
+    assert a.get() == b.get()
+
+    a = shared_ptr[A](new A())
+    b = dynamic_pointer_cast[B, A](a)
+    assert b.get() == NULL
diff --git a/tests/run/cpp_smart_ptr_helper.h b/tests/run/cpp_smart_ptr_helper.h
index 9081801f9..02d73868c 100644
--- a/tests/run/cpp_smart_ptr_helper.h
+++ b/tests/run/cpp_smart_ptr_helper.h
@@ -14,7 +14,7 @@ class CountAllocDealloc {
 
 template<typename T>
 struct FreePtr {
-  void operator()( T * t ) noexcept
+  void operator()( T * t )
   {
     if(t != nullptr) {
       delete t;
-- 
2.30.9