mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
Deprecated borrowed/stolen for borrowed_t{}/stolen_t{} (#771)
The constexpr static instances can cause linking failures if the compiler doesn't optimize away the reference, as reported in #770. There's no particularly nice way of fixing this in C++11/14: we can't inline definitions to match the declaration aren't permitted for non-templated static variables (C++17 *does* allows "inline" on variables, but that obviously doesn't help us.) One solution that could work around it is to add an extra inherited subclass to `object`'s hierarchy, but that's a bit of a messy solution and was decided against in #771 in favour of just deprecating (and eventually dropping) the constexpr statics. Fixes #770.
This commit is contained in:
parent
d6fdafb203
commit
6db60cd945
@ -714,16 +714,16 @@ public:
|
|||||||
using value_type = T;
|
using value_type = T;
|
||||||
|
|
||||||
array_t() : array(0, static_cast<const T *>(nullptr)) {}
|
array_t() : array(0, static_cast<const T *>(nullptr)) {}
|
||||||
array_t(handle h, borrowed_t) : array(h, borrowed) { }
|
array_t(handle h, borrowed_t) : array(h, borrowed_t{}) { }
|
||||||
array_t(handle h, stolen_t) : array(h, stolen) { }
|
array_t(handle h, stolen_t) : array(h, stolen_t{}) { }
|
||||||
|
|
||||||
PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
|
PYBIND11_DEPRECATED("Use array_t<T>::ensure() instead")
|
||||||
array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen) {
|
array_t(handle h, bool is_borrowed) : array(raw_array_t(h.ptr()), stolen_t{}) {
|
||||||
if (!m_ptr) PyErr_Clear();
|
if (!m_ptr) PyErr_Clear();
|
||||||
if (!is_borrowed) Py_XDECREF(h.ptr());
|
if (!is_borrowed) Py_XDECREF(h.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
array_t(const object &o) : array(raw_array_t(o.ptr()), stolen) {
|
array_t(const object &o) : array(raw_array_t(o.ptr()), stolen_t{}) {
|
||||||
if (!m_ptr) throw error_already_set();
|
if (!m_ptr) throw error_already_set();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,8 +234,13 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Tags for choosing constructors from raw PyObject *
|
// Tags for choosing constructors from raw PyObject *
|
||||||
struct borrowed_t { }; static constexpr borrowed_t borrowed{};
|
struct borrowed_t { };
|
||||||
struct stolen_t { }; static constexpr stolen_t stolen{};
|
struct stolen_t { };
|
||||||
|
// These can cause linkage problems; see #770
|
||||||
|
PYBIND11_DEPRECATED("Use of the `borrowed` static variable is deprecated; use `borrowed_t{}' instead")
|
||||||
|
static constexpr borrowed_t borrowed{};
|
||||||
|
PYBIND11_DEPRECATED("Use of the `stolen` static variable is deprecated; use `stolen_t{}' instead")
|
||||||
|
static constexpr stolen_t stolen{};
|
||||||
|
|
||||||
template <typename T> friend T reinterpret_borrow(handle);
|
template <typename T> friend T reinterpret_borrow(handle);
|
||||||
template <typename T> friend T reinterpret_steal(handle);
|
template <typename T> friend T reinterpret_steal(handle);
|
||||||
@ -259,7 +264,7 @@ public:
|
|||||||
// or
|
// or
|
||||||
py::tuple t = reinterpret_borrow<py::tuple>(p); // <-- `p` must be already be a `tuple`
|
py::tuple t = reinterpret_borrow<py::tuple>(p); // <-- `p` must be already be a `tuple`
|
||||||
\endrst */
|
\endrst */
|
||||||
template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed}; }
|
template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed_t{}}; }
|
||||||
|
|
||||||
/** \rst
|
/** \rst
|
||||||
Like `reinterpret_borrow`, but steals the reference.
|
Like `reinterpret_borrow`, but steals the reference.
|
||||||
@ -269,7 +274,7 @@ template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrow
|
|||||||
PyObject *p = PyObject_Str(obj);
|
PyObject *p = PyObject_Str(obj);
|
||||||
py::str s = reinterpret_steal<py::str>(p); // <-- `p` must be already be a `str`
|
py::str s = reinterpret_steal<py::str>(p); // <-- `p` must be already be a `str`
|
||||||
\endrst */
|
\endrst */
|
||||||
template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen}; }
|
template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen_t{}}; }
|
||||||
|
|
||||||
/** \defgroup python_builtins _
|
/** \defgroup python_builtins _
|
||||||
Unless stated otherwise, the following C++ functions behave the same
|
Unless stated otherwise, the following C++ functions behave the same
|
||||||
@ -674,9 +679,9 @@ NAMESPACE_END(detail)
|
|||||||
#define PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
#define PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||||
public: \
|
public: \
|
||||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<"#Name">() or reinterpret_steal<"#Name">()") \
|
PYBIND11_DEPRECATED("Use reinterpret_borrow<"#Name">() or reinterpret_steal<"#Name">()") \
|
||||||
Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed) : Parent(h, stolen)) { } \
|
Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed_t{}) : Parent(h, stolen_t{})) { } \
|
||||||
Name(handle h, borrowed_t) : Parent(h, borrowed) { } \
|
Name(handle h, borrowed_t) : Parent(h, borrowed_t{}) { } \
|
||||||
Name(handle h, stolen_t) : Parent(h, stolen) { } \
|
Name(handle h, stolen_t) : Parent(h, stolen_t{}) { } \
|
||||||
PYBIND11_DEPRECATED("Use py::isinstance<py::python_type>(obj) instead") \
|
PYBIND11_DEPRECATED("Use py::isinstance<py::python_type>(obj) instead") \
|
||||||
bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } \
|
bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } \
|
||||||
static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); }
|
static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); }
|
||||||
@ -684,7 +689,7 @@ NAMESPACE_END(detail)
|
|||||||
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
|
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \
|
||||||
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||||
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
|
/* This is deliberately not 'explicit' to allow implicit conversion from object: */ \
|
||||||
Name(const object &o) : Parent(ConvertFun(o.ptr()), stolen) { if (!m_ptr) throw error_already_set(); }
|
Name(const object &o) : Parent(ConvertFun(o.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); }
|
||||||
|
|
||||||
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \
|
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \
|
||||||
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
|
||||||
@ -778,13 +783,13 @@ public:
|
|||||||
PYBIND11_OBJECT_CVT(str, object, detail::PyUnicode_Check_Permissive, raw_str)
|
PYBIND11_OBJECT_CVT(str, object, detail::PyUnicode_Check_Permissive, raw_str)
|
||||||
|
|
||||||
str(const char *c, size_t n)
|
str(const char *c, size_t n)
|
||||||
: object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen) {
|
: object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
|
// 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects
|
||||||
str(const char *c = "")
|
str(const char *c = "")
|
||||||
: object(PyUnicode_FromString(c), stolen) {
|
: object(PyUnicode_FromString(c), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
if (!m_ptr) pybind11_fail("Could not allocate string object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,7 +801,7 @@ public:
|
|||||||
Return a string representation of the object. This is analogous to
|
Return a string representation of the object. This is analogous to
|
||||||
the ``str()`` function in Python.
|
the ``str()`` function in Python.
|
||||||
\endrst */
|
\endrst */
|
||||||
explicit str(handle h) : object(raw_str(h.ptr()), stolen) { }
|
explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { }
|
||||||
|
|
||||||
operator std::string() const {
|
operator std::string() const {
|
||||||
object temp = *this;
|
object temp = *this;
|
||||||
@ -846,12 +851,12 @@ public:
|
|||||||
|
|
||||||
// Allow implicit conversion:
|
// Allow implicit conversion:
|
||||||
bytes(const char *c = "")
|
bytes(const char *c = "")
|
||||||
: object(PYBIND11_BYTES_FROM_STRING(c), stolen) {
|
: object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes(const char *c, size_t n)
|
bytes(const char *c, size_t n)
|
||||||
: object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen) {
|
: object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,15 +905,15 @@ inline str::str(const bytes& b) {
|
|||||||
class none : public object {
|
class none : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT(none, object, detail::PyNone_Check)
|
PYBIND11_OBJECT(none, object, detail::PyNone_Check)
|
||||||
none() : object(Py_None, borrowed) { }
|
none() : object(Py_None, borrowed_t{}) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
class bool_ : public object {
|
class bool_ : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool)
|
PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool)
|
||||||
bool_() : object(Py_False, borrowed) { }
|
bool_() : object(Py_False, borrowed_t{}) { }
|
||||||
// Allow implicit conversion from and to `bool`:
|
// Allow implicit conversion from and to `bool`:
|
||||||
bool_(bool value) : object(value ? Py_True : Py_False, borrowed) { }
|
bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { }
|
||||||
operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; }
|
operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -923,7 +928,7 @@ private:
|
|||||||
class int_ : public object {
|
class int_ : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long)
|
PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long)
|
||||||
int_() : object(PyLong_FromLong(0), stolen) { }
|
int_() : object(PyLong_FromLong(0), stolen_t{}) { }
|
||||||
// Allow implicit conversion from C++ integral types:
|
// Allow implicit conversion from C++ integral types:
|
||||||
template <typename T,
|
template <typename T,
|
||||||
detail::enable_if_t<std::is_integral<T>::value, int> = 0>
|
detail::enable_if_t<std::is_integral<T>::value, int> = 0>
|
||||||
@ -963,10 +968,10 @@ class float_ : public object {
|
|||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float)
|
PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float)
|
||||||
// Allow implicit conversion from float/double:
|
// Allow implicit conversion from float/double:
|
||||||
float_(float value) : object(PyFloat_FromDouble((double) value), stolen) {
|
float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||||
}
|
}
|
||||||
float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen) {
|
float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
if (!m_ptr) pybind11_fail("Could not allocate float object!");
|
||||||
}
|
}
|
||||||
operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
|
operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
|
||||||
@ -977,7 +982,7 @@ class weakref : public object {
|
|||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check)
|
PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check)
|
||||||
explicit weakref(handle obj, handle callback = {})
|
explicit weakref(handle obj, handle callback = {})
|
||||||
: object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen) {
|
: object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate weak reference!");
|
if (!m_ptr) pybind11_fail("Could not allocate weak reference!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1003,17 +1008,17 @@ class capsule : public object {
|
|||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact)
|
||||||
PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()")
|
PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()")
|
||||||
capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed) : object(ptr, stolen)) { }
|
capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed_t{}) : object(ptr, stolen_t{})) { }
|
||||||
|
|
||||||
explicit capsule(const void *value)
|
explicit capsule(const void *value)
|
||||||
: object(PyCapsule_New(const_cast<void *>(value), nullptr, nullptr), stolen) {
|
: object(PyCapsule_New(const_cast<void *>(value), nullptr, nullptr), stolen_t{}) {
|
||||||
if (!m_ptr)
|
if (!m_ptr)
|
||||||
pybind11_fail("Could not allocate capsule object!");
|
pybind11_fail("Could not allocate capsule object!");
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_DEPRECATED("Please pass a destructor that takes a void pointer as input")
|
PYBIND11_DEPRECATED("Please pass a destructor that takes a void pointer as input")
|
||||||
capsule(const void *value, void (*destruct)(PyObject *))
|
capsule(const void *value, void (*destruct)(PyObject *))
|
||||||
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen) {
|
: object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen_t{}) {
|
||||||
if (!m_ptr)
|
if (!m_ptr)
|
||||||
pybind11_fail("Could not allocate capsule object!");
|
pybind11_fail("Could not allocate capsule object!");
|
||||||
}
|
}
|
||||||
@ -1052,7 +1057,7 @@ public:
|
|||||||
class tuple : public object {
|
class tuple : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple)
|
PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple)
|
||||||
explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen) {
|
explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
|
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
|
||||||
}
|
}
|
||||||
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
|
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
|
||||||
@ -1064,7 +1069,7 @@ public:
|
|||||||
class dict : public object {
|
class dict : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict)
|
PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict)
|
||||||
dict() : object(PyDict_New(), stolen) {
|
dict() : object(PyDict_New(), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
|
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
|
||||||
}
|
}
|
||||||
template <typename... Args,
|
template <typename... Args,
|
||||||
@ -1101,7 +1106,7 @@ public:
|
|||||||
class list : public object {
|
class list : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List)
|
PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List)
|
||||||
explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen) {
|
explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate list object!");
|
if (!m_ptr) pybind11_fail("Could not allocate list object!");
|
||||||
}
|
}
|
||||||
size_t size() const { return (size_t) PyList_Size(m_ptr); }
|
size_t size() const { return (size_t) PyList_Size(m_ptr); }
|
||||||
@ -1119,7 +1124,7 @@ class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check)
|
|||||||
class set : public object {
|
class set : public object {
|
||||||
public:
|
public:
|
||||||
PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New)
|
PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New)
|
||||||
set() : object(PySet_New(nullptr), stolen) {
|
set() : object(PySet_New(nullptr), stolen_t{}) {
|
||||||
if (!m_ptr) pybind11_fail("Could not allocate set object!");
|
if (!m_ptr) pybind11_fail("Could not allocate set object!");
|
||||||
}
|
}
|
||||||
size_t size() const { return (size_t) PySet_Size(m_ptr); }
|
size_t size() const { return (size_t) PySet_Size(m_ptr); }
|
||||||
|
Loading…
Reference in New Issue
Block a user