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
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace pybindit {
|
||||
@ -44,8 +46,10 @@ struct smart_holder {
|
||||
rtti_uqp_del{nullptr},
|
||||
vptr_deleter_guard_flag{false} {}
|
||||
|
||||
bool has_pointee() const { return vptr.get() != nullptr; }
|
||||
|
||||
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);
|
||||
if (!(*rtti_requested == *rtti_held)) {
|
||||
throw std::runtime_error(std::string("Incompatible RTTI (") + context +
|
||||
@ -54,7 +58,7 @@ struct smart_holder {
|
||||
}
|
||||
|
||||
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);
|
||||
if (!(*rtti_requested == *rtti_uqp_del)) {
|
||||
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) {
|
||||
throw std::runtime_error(std::string("Cannot disown this shared_ptr (") +
|
||||
context + ").");
|
||||
}
|
||||
}
|
||||
|
||||
void ensure_use_count_1(const char* context) {
|
||||
void ensure_use_count_1(const char* context) const {
|
||||
if (vptr.use_count() != 1) {
|
||||
throw std::runtime_error(std::string("Cannot disown use_count != 1 (") +
|
||||
context + ").");
|
||||
@ -77,7 +88,15 @@ struct smart_holder {
|
||||
}
|
||||
|
||||
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();
|
||||
rtti_held = &typeid(T);
|
||||
vptr_deleter_guard_flag = true;
|
||||
@ -93,7 +112,8 @@ struct smart_holder {
|
||||
}
|
||||
|
||||
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_vptr_deleter_guard_flag_true(context);
|
||||
ensure_use_count_1(context);
|
||||
@ -104,7 +124,7 @@ struct smart_holder {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* as_raw_ptr_unowned() {
|
||||
T* as_raw_ptr_unowned() const {
|
||||
static const char* context = "as_raw_ptr_unowned";
|
||||
ensure_compatible_rtti_held<T>(context);
|
||||
return static_cast<T*>(vptr.get());
|
||||
@ -122,7 +142,7 @@ struct smart_holder {
|
||||
|
||||
template <typename T>
|
||||
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>
|
||||
@ -156,7 +176,7 @@ struct smart_holder {
|
||||
}
|
||||
|
||||
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";
|
||||
ensure_compatible_rtti_held<T>(context);
|
||||
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