mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-29 16:37:13 +00:00
New tests/core/smart_holder_poc_test.cpp, using Catch2.
This commit is contained in:
parent
84bdaebf57
commit
5ab34305ae
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
namespace pybindit {
|
namespace pybindit {
|
||||||
@ -44,8 +46,10 @@ struct smart_holder {
|
|||||||
rtti_uqp_del{nullptr},
|
rtti_uqp_del{nullptr},
|
||||||
vptr_deleter_guard_flag{false} {}
|
vptr_deleter_guard_flag{false} {}
|
||||||
|
|
||||||
|
bool has_pointee() const { return vptr.get() != nullptr; }
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ensure_compatible_rtti_held(const char* context) {
|
void ensure_compatible_rtti_held(const char* context) const {
|
||||||
const std::type_info* rtti_requested = &typeid(T);
|
const std::type_info* rtti_requested = &typeid(T);
|
||||||
if (!(*rtti_requested == *rtti_held)) {
|
if (!(*rtti_requested == *rtti_held)) {
|
||||||
throw std::runtime_error(std::string("Incompatible RTTI (") + context +
|
throw std::runtime_error(std::string("Incompatible RTTI (") + context +
|
||||||
@ -54,7 +58,7 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename D>
|
template <typename D>
|
||||||
void ensure_compatible_rtti_uqp_del(const char* context) {
|
void ensure_compatible_rtti_uqp_del(const char* context) const {
|
||||||
const std::type_info* rtti_requested = &typeid(D);
|
const std::type_info* rtti_requested = &typeid(D);
|
||||||
if (!(*rtti_requested == *rtti_uqp_del)) {
|
if (!(*rtti_requested == *rtti_uqp_del)) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
@ -62,14 +66,21 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_vptr_deleter_guard_flag_true(const char* context) {
|
void ensure_has_pointee(const char* context) const {
|
||||||
|
if (!has_pointee()) {
|
||||||
|
throw std::runtime_error(std::string("Disowned holder (") + context +
|
||||||
|
").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ensure_vptr_deleter_guard_flag_true(const char* context) const {
|
||||||
if (rtti_uqp_del != nullptr) {
|
if (rtti_uqp_del != nullptr) {
|
||||||
throw std::runtime_error(std::string("Cannot disown this shared_ptr (") +
|
throw std::runtime_error(std::string("Cannot disown this shared_ptr (") +
|
||||||
context + ").");
|
context + ").");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_use_count_1(const char* context) {
|
void ensure_use_count_1(const char* context) const {
|
||||||
if (vptr.use_count() != 1) {
|
if (vptr.use_count() != 1) {
|
||||||
throw std::runtime_error(std::string("Cannot disown use_count != 1 (") +
|
throw std::runtime_error(std::string("Cannot disown use_count != 1 (") +
|
||||||
context + ").");
|
context + ").");
|
||||||
@ -77,7 +88,15 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void from_raw_ptr_owned(T* raw_ptr) {
|
const T& const_value_ref() const {
|
||||||
|
static const char* context = "const_value_ref";
|
||||||
|
ensure_compatible_rtti_held<T>(context);
|
||||||
|
ensure_has_pointee(context);
|
||||||
|
return *static_cast<T*>(vptr.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void from_raw_ptr_take_ownership(T* raw_ptr) {
|
||||||
clear();
|
clear();
|
||||||
rtti_held = &typeid(T);
|
rtti_held = &typeid(T);
|
||||||
vptr_deleter_guard_flag = true;
|
vptr_deleter_guard_flag = true;
|
||||||
@ -93,7 +112,8 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* as_raw_ptr_owned(const char* context = "as_raw_ptr_owned") {
|
T* as_raw_ptr_release_ownership(
|
||||||
|
const char* context = "as_raw_ptr_release_ownership") {
|
||||||
ensure_compatible_rtti_held<T>(context);
|
ensure_compatible_rtti_held<T>(context);
|
||||||
ensure_vptr_deleter_guard_flag_true(context);
|
ensure_vptr_deleter_guard_flag_true(context);
|
||||||
ensure_use_count_1(context);
|
ensure_use_count_1(context);
|
||||||
@ -104,7 +124,7 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* as_raw_ptr_unowned() {
|
T* as_raw_ptr_unowned() const {
|
||||||
static const char* context = "as_raw_ptr_unowned";
|
static const char* context = "as_raw_ptr_unowned";
|
||||||
ensure_compatible_rtti_held<T>(context);
|
ensure_compatible_rtti_held<T>(context);
|
||||||
return static_cast<T*>(vptr.get());
|
return static_cast<T*>(vptr.get());
|
||||||
@ -122,7 +142,7 @@ struct smart_holder {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::unique_ptr<T> as_unique_ptr() {
|
std::unique_ptr<T> as_unique_ptr() {
|
||||||
return std::unique_ptr<T>(as_raw_ptr_owned<T>("as_unique_ptr"));
|
return std::unique_ptr<T>(as_raw_ptr_release_ownership<T>("as_unique_ptr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename D>
|
template <typename T, typename D>
|
||||||
@ -156,7 +176,7 @@ struct smart_holder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::shared_ptr<T> as_shared_ptr() {
|
std::shared_ptr<T> as_shared_ptr() const {
|
||||||
static const char* context = "as_shared_ptr";
|
static const char* context = "as_shared_ptr";
|
||||||
ensure_compatible_rtti_held<T>(context);
|
ensure_compatible_rtti_held<T>(context);
|
||||||
return std::static_pointer_cast<T>(vptr);
|
return std::static_pointer_cast<T>(vptr);
|
||||||
|
99
tests/core/smart_holder_poc_test.cpp
Normal file
99
tests/core/smart_holder_poc_test.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include "pybind11/smart_holder_poc.h"
|
||||||
|
|
||||||
|
#define CATCH_CONFIG_MAIN
|
||||||
|
#include "catch.hpp"
|
||||||
|
|
||||||
|
using pybindit::memory::smart_holder;
|
||||||
|
|
||||||
|
namespace helpers {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct functor_builtin_delete {
|
||||||
|
void operator()(T* ptr) { delete ptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace helpers
|
||||||
|
|
||||||
|
TEST_CASE("from_raw_ptr_take_ownership=const_value_ref") {
|
||||||
|
smart_holder hld;
|
||||||
|
REQUIRE(!hld.has_pointee());
|
||||||
|
hld.from_raw_ptr_take_ownership(new int(19));
|
||||||
|
REQUIRE(hld.has_pointee());
|
||||||
|
REQUIRE(hld.const_value_ref<int>() == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("from_raw_ptr_unowned=const_value_ref") {
|
||||||
|
static int value = 19;
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_raw_ptr_unowned(&value);
|
||||||
|
REQUIRE(hld.const_value_ref<int>() == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("as_raw_ptr_release_ownership") {
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_raw_ptr_take_ownership(new int(19));
|
||||||
|
auto new_owner =
|
||||||
|
std::unique_ptr<int>(hld.as_raw_ptr_release_ownership<int>());
|
||||||
|
REQUIRE(!hld.has_pointee());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("as_raw_ptr_unowned") {
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_raw_ptr_take_ownership(new int(19));
|
||||||
|
int* raw_ptr = hld.as_raw_ptr_unowned<int>();
|
||||||
|
REQUIRE(hld.has_pointee());
|
||||||
|
REQUIRE(*raw_ptr == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("from_unique_ptr=const_value_ref") {
|
||||||
|
std::unique_ptr<int> orig_owner(new int(19));
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_unique_ptr(std::move(orig_owner));
|
||||||
|
REQUIRE(orig_owner.get() == nullptr);
|
||||||
|
REQUIRE(hld.const_value_ref<int>() == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("as_unique_ptr") {
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_raw_ptr_take_ownership(new int(19));
|
||||||
|
auto new_owner = hld.as_unique_ptr<int>();
|
||||||
|
REQUIRE(!hld.has_pointee());
|
||||||
|
REQUIRE(*new_owner == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("from_unique_ptr_with_deleter=const_value_ref") {
|
||||||
|
std::unique_ptr<int, helpers::functor_builtin_delete<int>> orig_owner(
|
||||||
|
new int(19));
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_unique_ptr_with_deleter(std::move(orig_owner));
|
||||||
|
REQUIRE(orig_owner.get() == nullptr);
|
||||||
|
REQUIRE(hld.const_value_ref<int>() == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("as_unique_ptr_with_deleter") {
|
||||||
|
std::unique_ptr<int, helpers::functor_builtin_delete<int>> orig_owner(
|
||||||
|
new int(19));
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_unique_ptr_with_deleter(std::move(orig_owner));
|
||||||
|
auto new_owner =
|
||||||
|
hld.as_unique_ptr_with_deleter<int,
|
||||||
|
helpers::functor_builtin_delete<int>>();
|
||||||
|
REQUIRE(!hld.has_pointee());
|
||||||
|
REQUIRE(*new_owner == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("from_shared_ptr=const_value_ref") {
|
||||||
|
std::shared_ptr<int> orig_owner(new int(19));
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_shared_ptr(orig_owner);
|
||||||
|
REQUIRE(orig_owner.get() != nullptr);
|
||||||
|
REQUIRE(hld.const_value_ref<int>() == 19);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("as_shared_ptr") {
|
||||||
|
smart_holder hld;
|
||||||
|
hld.from_raw_ptr_take_ownership(new int(19));
|
||||||
|
auto new_owner = hld.as_shared_ptr<int>();
|
||||||
|
REQUIRE(hld.has_pointee());
|
||||||
|
REQUIRE(*new_owner == 19);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user