Enable unique_ptr holder with mixed Deleters between base and derived types (#1353)

* Check default holder

-Recognize "std::unique_ptr<T, D>" as a default holder even if "D" doesn't match between base and derived holders

* Add test for unique_ptr<T, D> change
diff --git a/tests/test_smart_ptr.cpp b/tests/test_smart_ptr.cpp
index 098b182..5f1fd07 100644
--- a/tests/test_smart_ptr.cpp
+++ b/tests/test_smart_ptr.cpp
@@ -186,6 +186,32 @@
         .def(py::init<int>())
         .def_readwrite("value", &MyObject4::value);
 
+    // test_unique_deleter
+    // Object with std::unique_ptr<T, D> where D is not matching the base class
+    // Object with a protected destructor
+    class MyObject4a {
+    public:
+        MyObject4a(int i) {
+            value = i;
+            print_created(this);
+        };
+        int value;
+    protected:
+        virtual ~MyObject4a() { print_destroyed(this); }
+    };
+    py::class_<MyObject4a, std::unique_ptr<MyObject4a, py::nodelete>>(m, "MyObject4a")
+        .def(py::init<int>())
+        .def_readwrite("value", &MyObject4a::value);
+
+    // Object derived but with public destructor and no Deleter in default holder
+    class MyObject4b : public MyObject4a {
+    public:
+        MyObject4b(int i) : MyObject4a(i) { print_created(this); }
+        ~MyObject4b() { print_destroyed(this); }
+    };
+    py::class_<MyObject4b, MyObject4a>(m, "MyObject4b")
+        .def(py::init<int>());
+
     // test_large_holder
     class MyObject5 { // managed by huge_unique_ptr
     public:
diff --git a/tests/test_smart_ptr.py b/tests/test_smart_ptr.py
index 60f48b3..72b1c2a 100644
--- a/tests/test_smart_ptr.py
+++ b/tests/test_smart_ptr.py
@@ -115,6 +115,27 @@
     assert cstats.alive() == 1  # Leak, but that's intentional
 
 
+def test_unique_nodelete4a():
+    o = m.MyObject4a(23)
+    assert o.value == 23
+    cstats = ConstructorStats.get(m.MyObject4a)
+    assert cstats.alive() == 1
+    del o
+    assert cstats.alive() == 1  # Leak, but that's intentional
+
+
+def test_unique_deleter():
+    o = m.MyObject4b(23)
+    assert o.value == 23
+    cstats4a = ConstructorStats.get(m.MyObject4a)
+    assert cstats4a.alive() == 2  # Two becaue of previous test
+    cstats4b = ConstructorStats.get(m.MyObject4b)
+    assert cstats4b.alive() == 1
+    del o
+    assert cstats4a.alive() == 1  # Should now only be one leftover from previous test
+    assert cstats4b.alive() == 0  # Should be deleted
+
+
 def test_large_holder():
     o = m.MyObject5(5)
     assert o.value == 5