1 // cpp11 version: 0.3.1.1
2 // vendored on: 2021-08-11
5 #include <cstddef> // for nullptr_t, NULL
6 #include <memory> // for bad_weak_ptr
7 #include <type_traits> // for add_lvalue_reference
9 #include "cpp11/R.hpp" // for SEXP, SEXPREC, TYPEOF, R_NilValue, R_C...
10 #include "cpp11/protect.hpp" // for protect, safe, protect::function
11 #include "cpp11/r_bool.hpp" // for r_bool
12 #include "cpp11/r_vector.hpp" // for type_error
13 #include "cpp11/sexp.hpp" // for sexp
18 void default_deleter(T* obj) {
22 template <typename T, void Deleter(T*) = default_deleter<T>>
23 class external_pointer {
25 sexp data_ = R_NilValue;
27 static SEXP valid_type(SEXP data) {
28 if (TYPEOF(data) != EXTPTRSXP) {
29 throw type_error(EXTPTRSXP, TYPEOF(data));
35 static void r_deleter(SEXP p) {
36 if (TYPEOF(p) != EXTPTRSXP) return;
38 T* ptr = static_cast<T*>(R_ExternalPtrAddr(p));
44 R_ClearExternalPtr(p);
52 external_pointer() noexcept {}
53 external_pointer(std::nullptr_t) noexcept {}
55 external_pointer(SEXP data) : data_(valid_type(data)) {}
57 external_pointer(pointer p, bool use_deleter = true, bool finalize_on_exit = true)
58 : data_(safe[R_MakeExternalPtr]((void*)p, R_NilValue, R_NilValue)) {
60 R_RegisterCFinalizerEx(data_, r_deleter, static_cast<r_bool>(finalize_on_exit));
64 external_pointer(const external_pointer& rhs) {
65 data_ = safe[Rf_shallow_duplicate](rhs.data_);
68 external_pointer(external_pointer&& rhs) { reset(rhs.release()); }
70 external_pointer& operator=(external_pointer&& rhs) noexcept { reset(rhs.release()); }
72 external_pointer& operator=(std::nullptr_t) noexcept { reset(); };
74 operator SEXP() const noexcept { return data_; }
76 pointer get() const noexcept {
77 pointer addr = static_cast<T*>(R_ExternalPtrAddr(data_));
78 if (addr == nullptr) {
84 typename std::add_lvalue_reference<T>::type operator*() {
86 if (addr == nullptr) {
87 throw std::bad_weak_ptr();
92 pointer operator->() const {
94 if (addr == nullptr) {
95 throw std::bad_weak_ptr();
100 pointer release() noexcept {
101 if (get() == nullptr) {
105 R_ClearExternalPtr(data_);
110 void reset(pointer ptr = pointer()) {
111 SEXP old_data = data_;
112 data_ = safe[R_MakeExternalPtr]((void*)ptr, R_NilValue, R_NilValue);
116 void swap(external_pointer& other) noexcept {
117 SEXP tmp = other.data_;
122 operator bool() noexcept { return data_ != nullptr; }
125 template <class T, void Deleter(T*)>
126 void swap(external_pointer<T, Deleter>& lhs, external_pointer<T, Deleter>& rhs) noexcept {
130 template <class T, void Deleter(T*)>
131 bool operator==(const external_pointer<T, Deleter>& x,
132 const external_pointer<T, Deleter>& y) {
133 return x.data_ == y.data_;
136 template <class T, void Deleter(T*)>
137 bool operator!=(const external_pointer<T, Deleter>& x,
138 const external_pointer<T, Deleter>& y) {
139 return x.data_ != y.data_;
142 template <class T, void Deleter(T*)>
143 bool operator<(const external_pointer<T, Deleter>& x,
144 const external_pointer<T, Deleter>& y) {
145 return x.data_ < y.data_;
148 template <class T, void Deleter(T*)>
149 bool operator<=(const external_pointer<T, Deleter>& x,
150 const external_pointer<T, Deleter>& y) {
151 return x.data_ <= y.data_;
154 template <class T, void Deleter(T*)>
155 bool operator>(const external_pointer<T, Deleter>& x,
156 const external_pointer<T, Deleter>& y) {
157 return x.data_ > y.data_;
160 template <class T, void Deleter(T*)>
161 bool operator>=(const external_pointer<T, Deleter>& x,
162 const external_pointer<T, Deleter>& y) {
163 return x.data_ >= y.data_;