-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Copying tests as-is from xxx_value_ptr_xxx_holder branch.
https://github.com/rwgk/pybind11/tree/xxx_value_ptr_xxx_holder Systematically exercising casting between shared_ptr<base>, shared_ptr<derived>.
- Loading branch information
Ralf W. Grosse-Kunstleve
committed
Dec 18, 2020
1 parent
b63f0c6
commit 3b34392
Showing
2 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#include "pybind11_tests.h" | ||
|
||
#include <iostream> | ||
#include <memory> | ||
|
||
namespace pybind11_tests { | ||
namespace smart_ptr_base_derived { | ||
|
||
inline void to_cout(std::string text) { std::cout << text << std::endl; } | ||
|
||
class cbase { | ||
public: | ||
int get_int() const { return 90146438; } | ||
}; | ||
|
||
class cderived : public cbase { | ||
public: | ||
// Printing from constructor & destructor for simple external validation. | ||
cderived() { | ||
std::cout << std::endl << "cderived+" << std::endl; | ||
} | ||
~cderived() { | ||
std::cout << std::endl << "cderived-" << std::endl; | ||
} | ||
int get_int() const { return 31607978; } | ||
int base_get_int(const cbase& base) { return get_int() + base.get_int(); } | ||
}; | ||
|
||
class vbase { | ||
public: | ||
virtual ~vbase() {} | ||
virtual int get_int() const = 0; | ||
}; | ||
|
||
class vderived : public vbase { | ||
public: | ||
// Printing from constructor & destructor for simple external validation. | ||
vderived() { | ||
std::cout << std::endl << "vderived+" << std::endl; | ||
} | ||
~vderived() { | ||
std::cout << std::endl << "vderived-" << std::endl; | ||
} | ||
int get_int() const override { return 29852452; } | ||
int base_get_int(const vbase& base) { return get_int() + base.get_int(); } | ||
}; | ||
|
||
class vrederived : public vderived {}; | ||
|
||
inline std::unique_ptr<cbase> | ||
make_unique_cderived_up_cast() { | ||
// Undefined Behavior (pure C++ problem, NOT a pybind11 problem): | ||
// cderived destructor does not run. | ||
return std::unique_ptr<cderived>(new cderived); | ||
} | ||
|
||
inline std::shared_ptr<cderived> | ||
make_shared_cderived(bool use_custom_deleter = false) { | ||
if (use_custom_deleter) { | ||
return std::shared_ptr<cderived>( | ||
new cderived, [](cderived *p) { delete p; }); | ||
} | ||
return std::shared_ptr<cderived>(new cderived); | ||
} | ||
|
||
inline std::shared_ptr<cbase> | ||
make_shared_cderived_up_cast(bool use_custom_deleter = false) { | ||
return make_shared_cderived(use_custom_deleter); | ||
} | ||
|
||
inline int pass_unique_cbase(std::unique_ptr<cbase> cb) { | ||
return cb->get_int(); | ||
} | ||
|
||
inline int pass_shared_cbase(std::shared_ptr<cbase> cb) { | ||
return cb->get_int(); | ||
} | ||
|
||
inline int pass_shared_cderived(std::shared_ptr<cderived> cd) { | ||
return cd->get_int(); | ||
} | ||
|
||
inline std::unique_ptr<vbase> | ||
make_unique_vderived_up_cast() { | ||
// Well-defined behavior because vderived has a virtual destructor. | ||
return std::unique_ptr<vderived>(new vderived); | ||
} | ||
|
||
inline std::shared_ptr<vderived> | ||
make_shared_vderived(bool use_custom_deleter = false) { | ||
if (use_custom_deleter) { | ||
return std::shared_ptr<vderived>( | ||
new vderived, [](vderived *p) { delete p; }); | ||
} | ||
return std::shared_ptr<vderived>(new vderived); | ||
} | ||
|
||
inline std::shared_ptr<vbase> | ||
make_shared_vderived_up_cast(bool use_custom_deleter = false) { | ||
return make_shared_vderived(use_custom_deleter); | ||
} | ||
|
||
inline int pass_unique_vbase(std::unique_ptr<vbase> vb) { | ||
return vb->get_int(); | ||
} | ||
|
||
inline int pass_shared_vbase(std::shared_ptr<vbase> vb) { | ||
return vb->get_int(); | ||
} | ||
|
||
inline int pass_shared_vderived(std::shared_ptr<vderived> vd) { | ||
return vd->get_int(); | ||
} | ||
|
||
inline int pass_shared_vrederived(std::shared_ptr<vrederived> vr) { | ||
return vr->get_int(); | ||
} | ||
|
||
TEST_SUBMODULE(smart_ptr_base_derived, m) { | ||
m.def("to_cout", to_cout); | ||
|
||
py::class_<cbase, std::shared_ptr<cbase>>(m, "cbase") | ||
.def(py::init<>()) | ||
.def("get_int", &cbase::get_int); | ||
|
||
py::class_<cderived, cbase, std::shared_ptr<cderived>>(m, "cderived") | ||
.def(py::init<>()) | ||
.def("get_int", &cderived::get_int); | ||
|
||
py::class_<vbase, std::shared_ptr<vbase>>(m, "vbase") | ||
.def("get_int", &vbase::get_int); | ||
|
||
py::class_<vderived, vbase, std::shared_ptr<vderived>>(m, "vderived") | ||
.def(py::init<>()); | ||
|
||
py::class_<vrederived, vderived, std::shared_ptr<vrederived>>(m, "vrederived") | ||
.def(py::init<>()); | ||
|
||
m.def("make_shared_cderived", | ||
make_shared_cderived, | ||
py::arg("use_custom_deleter") = false); | ||
m.def("make_shared_cderived_up_cast", | ||
make_shared_cderived_up_cast, | ||
py::arg("use_custom_deleter") = false); | ||
m.def("pass_shared_cbase", pass_shared_cbase); | ||
m.def("pass_shared_cderived", pass_shared_cderived); | ||
|
||
m.def("make_shared_vderived", | ||
make_shared_vderived, | ||
py::arg("use_custom_deleter") = false); | ||
m.def("make_shared_vderived_up_cast", | ||
make_shared_vderived_up_cast, | ||
py::arg("use_custom_deleter") = false); | ||
m.def("pass_shared_vbase", pass_shared_vbase); | ||
m.def("pass_shared_vderived", pass_shared_vderived); | ||
m.def("pass_shared_vrederived", pass_shared_vrederived); | ||
} | ||
|
||
} // namespace smart_ptr_base_derived | ||
} // namespace pybind11_tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# -*- coding: utf-8 -*- | ||
import pytest | ||
|
||
from pybind11_tests import smart_ptr_base_derived as m | ||
|
||
CBASE_GET_INT_RESULT = 90146438 | ||
CDERIVED_GET_INT_RESULT = 31607978 | ||
VDERIVED_GET_INT_RESULT = 29852452 | ||
|
||
def test_concrete(): | ||
m.to_cout("") | ||
m.to_cout("") | ||
m.to_cout("make_shared_cderived") | ||
cd = m.make_shared_cderived() | ||
assert cd.get_int() == CDERIVED_GET_INT_RESULT | ||
m.pass_shared_cderived(cd) | ||
m.pass_shared_cbase(cd) | ||
cb = m.make_shared_cderived_up_cast() | ||
assert cb.get_int() == CBASE_GET_INT_RESULT | ||
m.pass_shared_cbase(cb) | ||
with pytest.raises(TypeError): | ||
m.pass_shared_cderived(cb) | ||
m.to_cout("") | ||
|
||
def test_virtual(): | ||
m.to_cout("") | ||
m.to_cout("") | ||
m.to_cout("make_shared_vderived") | ||
vd = m.make_shared_vderived() | ||
assert vd.get_int() == VDERIVED_GET_INT_RESULT | ||
m.pass_shared_vderived(vd) | ||
m.pass_shared_vbase(vd) | ||
vd_uc = m.make_shared_vderived_up_cast() | ||
assert vd_uc.get_int() == VDERIVED_GET_INT_RESULT | ||
assert isinstance(vd_uc, m.vderived) # pybind11 un-did upcast. | ||
m.pass_shared_vbase(vd_uc) | ||
m.pass_shared_vderived(vd_uc) | ||
with pytest.raises(TypeError): | ||
m.pass_shared_vrederived(vd_uc) | ||
m.to_cout("") |