Make handle and related classes const correct.

This gives handle classes a typical pointer semantics with respects to
constness.
This commit is contained in:
Tomasz Miąsko 2015-12-28 08:11:16 +01:00
parent 45f7c65594
commit 875df5528d
4 changed files with 38 additions and 40 deletions

View File

@ -59,31 +59,31 @@ Without reference counting
Creates a :class:`handle` from the given raw Python object pointer.
.. function:: PyObject * handle::ptr()
.. function:: PyObject * handle::ptr() const
Return the ``PyObject *`` underlying a :class:`handle`.
.. function:: void handle::inc_ref()
.. function:: void handle::inc_ref() const
Manually increase the reference count of the Python object. Usually, it is
preferable to use the :class:`object` class which derives from
:class:`handle` and calls this function automatically.
.. function:: void handle::dec_ref()
.. function:: void handle::dec_ref() const
Manually decrease the reference count of the Python object. Usually, it is
preferable to use the :class:`object` class which derives from
:class:`handle` and calls this function automatically.
.. function:: void handle::ref_count()
.. function:: void handle::ref_count() const
Return the object's current reference count
.. function:: handle handle::get_type()
.. function:: handle handle::get_type() const
Return a handle to the Python type object underlying the instance
.. function detail::accessor handle::operator[](handle key)
.. function detail::accessor handle::operator[](handle key) const
Return an internal functor to invoke the object's sequence protocol.
Casting the returned ``detail::accessor`` instance to a :class:`handle` or
@ -91,12 +91,12 @@ Without reference counting
Assigning a :class:`handle` or :class:`object` subclass causes a call to
``__setitem__``.
.. function detail::accessor handle::operator[](const char *key)
.. function detail::accessor handle::operator[](const char *key) const
See the above function (the only difference is that they key is provided as
a string literal).
.. function detail::accessor handle::attr(handle key)
.. function detail::accessor handle::attr(handle key) const
Return an internal functor to access the object's attributes.
Casting the returned ``detail::accessor`` instance to a :class:`handle` or
@ -104,7 +104,7 @@ Without reference counting
Assigning a :class:`handle` or :class:`object` subclass causes a call to
``__setattr``.
.. function detail::accessor handle::attr(const char *key)
.. function detail::accessor handle::attr(const char *key) const
See the above function (the only difference is that they key is provided as
a string literal).
@ -123,7 +123,7 @@ Without reference counting
Attempt to cast the Python object into the given C++ type. A
:class:`cast_error` will be throw upon failure.
.. function:: template <typename ... Args> object handle::call(Args&&... args)
.. function:: template <typename ... Args> object handle::call(Args&&... args) const
Assuming the Python object is a function or implements the ``__call__``
protocol, ``call()`` invokes the underlying function, passing an arbitrary
@ -169,7 +169,7 @@ With reference counting
.. function:: object::~object()
Constructor, which automatically calls :func:`handle::dec_ref()`.
Destructor, which automatically calls :func:`handle::dec_ref()`.
Convenience classes for specific Python types
=============================================

View File

@ -597,7 +597,7 @@ template <typename T> inline object cast(const T &value, return_value_policy pol
template <typename T> inline T handle::cast() const { return pybind11::cast<T>(m_ptr); }
template <> inline void handle::cast() const { return; }
template <typename... Args> inline object handle::call(Args&&... args_) {
template <typename... Args> inline object handle::call(Args&&... args_) const {
const size_t size = sizeof...(Args);
std::array<PyObject *, size> args{
{ detail::type_caster<typename detail::decay<Args>::type>::cast(

View File

@ -129,7 +129,7 @@ public:
PYBIND11_OBJECT_CVT(array_t, array, is_non_null, m_ptr = ensure(m_ptr));
array_t() : array() { }
static bool is_non_null(PyObject *ptr) { return ptr != nullptr; }
PyObject *ensure(PyObject *ptr) {
static PyObject *ensure(PyObject *ptr) {
if (ptr == nullptr)
return nullptr;
API &api = lookup_api();

View File

@ -29,21 +29,20 @@ public:
handle() : m_ptr(nullptr) { }
handle(const handle &other) : m_ptr(other.m_ptr) { }
handle(PyObject *ptr) : m_ptr(ptr) { }
PyObject *ptr() { return m_ptr; }
const PyObject *ptr() const { return m_ptr; }
PyObject *ptr() const { return m_ptr; }
void inc_ref() const { Py_XINCREF(m_ptr); }
void dec_ref() const { Py_XDECREF(m_ptr); }
int ref_count() const { return (int) Py_REFCNT(m_ptr); }
handle get_type() { return (PyObject *) Py_TYPE(m_ptr); }
inline iterator begin();
inline iterator end();
inline detail::accessor operator[](handle key);
inline detail::accessor operator[](const char *key);
inline detail::accessor attr(handle key);
inline detail::accessor attr(const char *key);
handle get_type() const { return (PyObject *) Py_TYPE(m_ptr); }
inline iterator begin() const;
inline iterator end() const;
inline detail::accessor operator[](handle key) const;
inline detail::accessor operator[](const char *key) const;
inline detail::accessor attr(handle key) const;
inline detail::accessor attr(const char *key) const;
inline pybind11::str str() const;
template <typename T> T cast() const;
template <typename ... Args> object call(Args&&... args_);
template <typename ... Args> object call(Args&&... args_) const;
operator bool() const { return m_ptr != nullptr; }
bool check() const { return m_ptr != nullptr; }
protected:
@ -88,7 +87,6 @@ public:
}
bool operator==(const iterator &it) const { return *it == **this; }
bool operator!=(const iterator &it) const { return *it != **this; }
object operator*() { return value; }
const object &operator*() const { return value; }
bool check() const { return PyIter_Check(ptr()); }
private:
@ -201,7 +199,7 @@ public:
pos = -1;
return *this;
}
std::pair<object, object> operator*() {
std::pair<object, object> operator*() const {
return std::make_pair(object(key, true), object(value, true));
}
bool operator==(const dict_iterator &it) const { return it.pos == pos; }
@ -237,12 +235,12 @@ inline bool PyLong_Check_(PyObject *o) {
NAMESPACE_END(detail)
inline detail::accessor handle::operator[](handle key) { return detail::accessor(ptr(), key.ptr(), false); }
inline detail::accessor handle::operator[](const char *key) { return detail::accessor(ptr(), key, false); }
inline detail::accessor handle::attr(handle key) { return detail::accessor(ptr(), key.ptr(), true); }
inline detail::accessor handle::attr(const char *key) { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() { return iterator(PyObject_GetIter(ptr())); }
inline iterator handle::end() { return iterator(nullptr); }
inline detail::accessor handle::operator[](handle key) const { return detail::accessor(ptr(), key.ptr(), false); }
inline detail::accessor handle::operator[](const char *key) const { return detail::accessor(ptr(), key, false); }
inline detail::accessor handle::attr(handle key) const { return detail::accessor(ptr(), key.ptr(), true); }
inline detail::accessor handle::attr(const char *key) const { return detail::accessor(ptr(), key, true); }
inline iterator handle::begin() const { return iterator(PyObject_GetIter(ptr())); }
inline iterator handle::end() const { return iterator(nullptr); }
#define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, CvtStmt) \
Name(const handle &h, bool borrowed) : Parent(h, borrowed) { CvtStmt; } \
@ -375,7 +373,7 @@ public:
PYBIND11_OBJECT(tuple, object, PyTuple_Check)
tuple(size_t size = 0) : object(PyTuple_New((Py_ssize_t) size), false) { }
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
detail::tuple_accessor operator[](size_t index) { return detail::tuple_accessor(ptr(), index); }
detail::tuple_accessor operator[](size_t index) const { return detail::tuple_accessor(ptr(), index); }
};
class dict : public object {
@ -383,9 +381,9 @@ public:
PYBIND11_OBJECT(dict, object, PyDict_Check)
dict() : object(PyDict_New(), false) { }
size_t size() const { return (size_t) PyDict_Size(m_ptr); }
detail::dict_iterator begin() { return (++detail::dict_iterator(ptr(), 0)); }
detail::dict_iterator end() { return detail::dict_iterator(); }
void clear() { PyDict_Clear(ptr()); }
detail::dict_iterator begin() const { return (++detail::dict_iterator(ptr(), 0)); }
detail::dict_iterator end() const { return detail::dict_iterator(); }
void clear() const { PyDict_Clear(ptr()); }
};
class list : public object {
@ -393,8 +391,8 @@ public:
PYBIND11_OBJECT(list, object, PyList_Check)
list(size_t size = 0) : object(PyList_New((ssize_t) size), false) { }
size_t size() const { return (size_t) PyList_Size(m_ptr); }
detail::list_accessor operator[](size_t index) { return detail::list_accessor(ptr(), index); }
void append(const object &object) { PyList_Append(m_ptr, (PyObject *) object.ptr()); }
detail::list_accessor operator[](size_t index) const { return detail::list_accessor(ptr(), index); }
void append(const object &object) const { PyList_Append(m_ptr, (PyObject *) object.ptr()); }
};
class set : public object {
@ -402,15 +400,15 @@ public:
PYBIND11_OBJECT(set, object, PySet_Check)
set() : object(PySet_New(nullptr), false) { }
size_t size() const { return (size_t) PySet_Size(m_ptr); }
void add(const object &object) { PySet_Add(m_ptr, (PyObject *) object.ptr()); }
void clear() { PySet_Clear(ptr()); }
void add(const object &object) const { PySet_Add(m_ptr, (PyObject *) object.ptr()); }
void clear() const { PySet_Clear(ptr()); }
};
class function : public object {
public:
PYBIND11_OBJECT_DEFAULT(function, object, PyFunction_Check)
bool is_cpp_function() {
bool is_cpp_function() const {
PyObject *ptr = detail::get_function(m_ptr);
return ptr != nullptr && PyCFunction_Check(ptr);
}