Resolve empty statement warning when using PYBIND11_OVERLOAD_PURE_NAME and PYBIND11_OVERLOAD_PURE (#2325)

* Wrap PYBIND11_OVERLOAD_NAME and PYBIND11_OVERLOAD_PURE_NAME in do { ... } while (false), and resolve trailing semicolon

* Deprecate PYBIND11_OVERLOAD_* and get_overload in favor of PYBIND11_OVERRIDE_* and get_override

* Correct erroneous usage of 'overload' instead of 'override' in the implementation and internals

* Fix tests to use non-deprecated PYBIND11_OVERRIDE_* macros

* Update docs to use override instead of overload where appropriate, and add warning about deprecated aliases

* Add semicolons to deprecated PYBIND11_OVERLOAD macros to match original behavior

* Remove deprecation of PYBIND11_OVERLOAD_* macros and get_overload

* Add note to changelog and upgrade guide
This commit is contained in:
Yannick Jadoul 2020-09-15 14:56:20 +02:00 committed by GitHub
parent 9df13835c8
commit d65e34d61d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 169 additions and 119 deletions

View File

@ -29,9 +29,9 @@ The following Python snippet demonstrates the intended usage from the Python sid
from example import print from example import print
print(A()) print(A())
To register the necessary conversion routines, it is necessary to add To register the necessary conversion routines, it is necessary to add an
a partial overload to the ``pybind11::detail::type_caster<T>`` template. instantiation of the ``pybind11::detail::type_caster<T>`` template.
Although this is an implementation detail, adding partial overloads to this Although this is an implementation detail, adding an instantiation of this
type is explicitly allowed. type is explicitly allowed.
.. code-block:: cpp .. code-block:: cpp

View File

@ -157,7 +157,7 @@ the declaration
before any binding code (e.g. invocations to ``class_::def()``, etc.). This before any binding code (e.g. invocations to ``class_::def()``, etc.). This
macro must be specified at the top level (and outside of any namespaces), since macro must be specified at the top level (and outside of any namespaces), since
it instantiates a partial template overload. If your binding code consists of it adds a template instantiation of ``type_caster``. If your binding code consists of
multiple compilation units, it must be present in every file (typically via a multiple compilation units, it must be present in every file (typically via a
common header) preceding any usage of ``std::vector<int>``. Opaque types must common header) preceding any usage of ``std::vector<int>``. Opaque types must
also have a corresponding ``class_`` declaration to associate them with a name also have a corresponding ``class_`` declaration to associate them with a name

View File

@ -71,7 +71,7 @@ helper class that is defined as follows:
/* Trampoline (need one for each virtual function) */ /* Trampoline (need one for each virtual function) */
std::string go(int n_times) override { std::string go(int n_times) override {
PYBIND11_OVERLOAD_PURE( PYBIND11_OVERRIDE_PURE(
std::string, /* Return type */ std::string, /* Return type */
Animal, /* Parent class */ Animal, /* Parent class */
go, /* Name of function in C++ (must match Python name) */ go, /* Name of function in C++ (must match Python name) */
@ -80,10 +80,10 @@ helper class that is defined as follows:
} }
}; };
The macro :c:macro:`PYBIND11_OVERLOAD_PURE` should be used for pure virtual The macro :c:macro:`PYBIND11_OVERRIDE_PURE` should be used for pure virtual
functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have functions, and :c:macro:`PYBIND11_OVERRIDE` should be used for functions which have
a default implementation. There are also two alternate macros a default implementation. There are also two alternate macros
:c:macro:`PYBIND11_OVERLOAD_PURE_NAME` and :c:macro:`PYBIND11_OVERLOAD_NAME` which :c:macro:`PYBIND11_OVERRIDE_PURE_NAME` and :c:macro:`PYBIND11_OVERRIDE_NAME` which
take a string-valued name argument between the *Parent class* and *Name of the take a string-valued name argument between the *Parent class* and *Name of the
function* slots, which defines the name of function in Python. This is required function* slots, which defines the name of function in Python. This is required
when the C++ and Python versions of the when the C++ and Python versions of the
@ -122,7 +122,7 @@ Bindings should be made against the actual class, not the trampoline helper clas
Note, however, that the above is sufficient for allowing python classes to Note, however, that the above is sufficient for allowing python classes to
extend ``Animal``, but not ``Dog``: see :ref:`virtual_and_inheritance` for the extend ``Animal``, but not ``Dog``: see :ref:`virtual_and_inheritance` for the
necessary steps required to providing proper overload support for inherited necessary steps required to providing proper overriding support for inherited
classes. classes.
The Python session below shows how to override ``Animal::go`` and invoke it via The Python session below shows how to override ``Animal::go`` and invoke it via
@ -181,15 +181,24 @@ Please take a look at the :ref:`macro_notes` before using this feature.
- because in these cases there is no C++ variable to reference (the value - because in these cases there is no C++ variable to reference (the value
is stored in the referenced Python variable), pybind11 provides one in is stored in the referenced Python variable), pybind11 provides one in
the PYBIND11_OVERLOAD macros (when needed) with static storage duration. the PYBIND11_OVERRIDE macros (when needed) with static storage duration.
Note that this means that invoking the overloaded method on *any* Note that this means that invoking the overridden method on *any*
instance will change the referenced value stored in *all* instances of instance will change the referenced value stored in *all* instances of
that type. that type.
- Attempts to modify a non-const reference will not have the desired - Attempts to modify a non-const reference will not have the desired
effect: it will change only the static cache variable, but this change effect: it will change only the static cache variable, but this change
will not propagate to underlying Python instance, and the change will be will not propagate to underlying Python instance, and the change will be
replaced the next time the overload is invoked. replaced the next time the override is invoked.
.. warning::
The :c:macro:`PYBIND11_OVERRIDE` and accompanying macros used to be called
``PYBIND11_OVERLOAD`` up until pybind11 v2.5.0, and :func:`get_override`
used to be called ``get_overload``. This naming was corrected and the older
macro and function names have been deprecated, in order to reduce confusion
with overloaded functions and methods and ``py::overload_cast`` (see
:ref:`classes`).
.. seealso:: .. seealso::
@ -237,20 +246,20 @@ override the ``name()`` method):
class PyAnimal : public Animal { class PyAnimal : public Animal {
public: public:
using Animal::Animal; // Inherit constructors using Animal::Animal; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Animal, go, n_times); } std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Animal, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Animal, name, ); } std::string name() override { PYBIND11_OVERRIDE(std::string, Animal, name, ); }
}; };
class PyDog : public Dog { class PyDog : public Dog {
public: public:
using Dog::Dog; // Inherit constructors using Dog::Dog; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD(std::string, Dog, go, n_times); } std::string go(int n_times) override { PYBIND11_OVERRIDE(std::string, Dog, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Dog, name, ); } std::string name() override { PYBIND11_OVERRIDE(std::string, Dog, name, ); }
std::string bark() override { PYBIND11_OVERLOAD(std::string, Dog, bark, ); } std::string bark() override { PYBIND11_OVERRIDE(std::string, Dog, bark, ); }
}; };
.. note:: .. note::
Note the trailing commas in the ``PYBIND11_OVERLOAD`` calls to ``name()`` Note the trailing commas in the ``PYBIND11_OVERIDE`` calls to ``name()``
and ``bark()``. These are needed to portably implement a trampoline for a and ``bark()``. These are needed to portably implement a trampoline for a
function that does not take any arguments. For functions that take function that does not take any arguments. For functions that take
a nonzero number of arguments, the trailing comma must be omitted. a nonzero number of arguments, the trailing comma must be omitted.
@ -265,9 +274,9 @@ declare or override any virtual methods itself:
class PyHusky : public Husky { class PyHusky : public Husky {
public: public:
using Husky::Husky; // Inherit constructors using Husky::Husky; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Husky, go, n_times); } std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Husky, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Husky, name, ); } std::string name() override { PYBIND11_OVERRIDE(std::string, Husky, name, ); }
std::string bark() override { PYBIND11_OVERLOAD(std::string, Husky, bark, ); } std::string bark() override { PYBIND11_OVERRIDE(std::string, Husky, bark, ); }
}; };
There is, however, a technique that can be used to avoid this duplication There is, however, a technique that can be used to avoid this duplication
@ -280,15 +289,15 @@ follows:
template <class AnimalBase = Animal> class PyAnimal : public AnimalBase { template <class AnimalBase = Animal> class PyAnimal : public AnimalBase {
public: public:
using AnimalBase::AnimalBase; // Inherit constructors using AnimalBase::AnimalBase; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, AnimalBase, go, n_times); } std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, AnimalBase, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, AnimalBase, name, ); } std::string name() override { PYBIND11_OVERRIDE(std::string, AnimalBase, name, ); }
}; };
template <class DogBase = Dog> class PyDog : public PyAnimal<DogBase> { template <class DogBase = Dog> class PyDog : public PyAnimal<DogBase> {
public: public:
using PyAnimal<DogBase>::PyAnimal; // Inherit constructors using PyAnimal<DogBase>::PyAnimal; // Inherit constructors
// Override PyAnimal's pure virtual go() with a non-pure one: // Override PyAnimal's pure virtual go() with a non-pure one:
std::string go(int n_times) override { PYBIND11_OVERLOAD(std::string, DogBase, go, n_times); } std::string go(int n_times) override { PYBIND11_OVERRIDE(std::string, DogBase, go, n_times); }
std::string bark() override { PYBIND11_OVERLOAD(std::string, DogBase, bark, ); } std::string bark() override { PYBIND11_OVERRIDE(std::string, DogBase, bark, ); }
}; };
This technique has the advantage of requiring just one trampoline method to be This technique has the advantage of requiring just one trampoline method to be
@ -341,7 +350,7 @@ valid for the trampoline class but not the registered class. This is primarily
for performance reasons: when the trampoline class is not needed for anything for performance reasons: when the trampoline class is not needed for anything
except virtual method dispatching, not initializing the trampoline class except virtual method dispatching, not initializing the trampoline class
improves performance by avoiding needing to do a run-time check to see if the improves performance by avoiding needing to do a run-time check to see if the
inheriting python instance has an overloaded method. inheriting python instance has an overridden method.
Sometimes, however, it is useful to always initialize a trampoline class as an Sometimes, however, it is useful to always initialize a trampoline class as an
intermediate class that does more than just handle virtual method dispatching. intermediate class that does more than just handle virtual method dispatching.
@ -372,7 +381,7 @@ references (See also :ref:`faq_reference_arguments`). Another way of solving
this is to use the method body of the trampoline class to do conversions to the this is to use the method body of the trampoline class to do conversions to the
input and return of the Python method. input and return of the Python method.
The main building block to do so is the :func:`get_overload`, this function The main building block to do so is the :func:`get_override`, this function
allows retrieving a method implemented in Python from within the trampoline's allows retrieving a method implemented in Python from within the trampoline's
methods. Consider for example a C++ method which has the signature methods. Consider for example a C++ method which has the signature
``bool myMethod(int32_t& value)``, where the return indicates whether ``bool myMethod(int32_t& value)``, where the return indicates whether
@ -384,10 +393,10 @@ Python side by allowing the Python function to return ``None`` or an ``int``:
bool MyClass::myMethod(int32_t& value) bool MyClass::myMethod(int32_t& value)
{ {
pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope. pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope.
// Try to look up the overloaded method on the Python side. // Try to look up the overridden method on the Python side.
pybind11::function overload = pybind11::get_overload(this, "myMethod"); pybind11::function override = pybind11::get_override(this, "myMethod");
if (overload) { // method is found if (override) { // method is found
auto obj = overload(value); // Call the Python function. auto obj = override(value); // Call the Python function.
if (py::isinstance<py::int_>(obj)) { // check if it returned a Python integer type if (py::isinstance<py::int_>(obj)) { // check if it returned a Python integer type
value = obj.cast<int32_t>(); // Cast it and assign it to the value. value = obj.cast<int32_t>(); // Cast it and assign it to the value.
return true; // Return true; value should be used. return true; // Return true; value should be used.
@ -1104,7 +1113,7 @@ described trampoline:
class Trampoline : public A { class Trampoline : public A {
public: public:
int foo() const override { PYBIND11_OVERLOAD(int, A, foo, ); } int foo() const override { PYBIND11_OVERRIDE(int, A, foo, ); }
}; };
class Publicist : public A { class Publicist : public A {

View File

@ -7,14 +7,14 @@ General notes regarding convenience macros
========================================== ==========================================
pybind11 provides a few convenience macros such as pybind11 provides a few convenience macros such as
:func:`PYBIND11_DECLARE_HOLDER_TYPE` and ``PYBIND11_OVERLOAD_*``. Since these :func:`PYBIND11_DECLARE_HOLDER_TYPE` and ``PYBIND11_OVERRIDE_*``. Since these
are "just" macros that are evaluated in the preprocessor (which has no concept are "just" macros that are evaluated in the preprocessor (which has no concept
of types), they *will* get confused by commas in a template argument; for of types), they *will* get confused by commas in a template argument; for
example, consider: example, consider:
.. code-block:: cpp .. code-block:: cpp
PYBIND11_OVERLOAD(MyReturnType<T1, T2>, Class<T3, T4>, func) PYBIND11_OVERRIDE(MyReturnType<T1, T2>, Class<T3, T4>, func)
The limitation of the C preprocessor interprets this as five arguments (with new The limitation of the C preprocessor interprets this as five arguments (with new
arguments beginning after each comma) rather than three. To get around this, arguments beginning after each comma) rather than three. To get around this,
@ -26,10 +26,10 @@ using the ``PYBIND11_TYPE`` macro:
// Version 1: using a type alias // Version 1: using a type alias
using ReturnType = MyReturnType<T1, T2>; using ReturnType = MyReturnType<T1, T2>;
using ClassType = Class<T3, T4>; using ClassType = Class<T3, T4>;
PYBIND11_OVERLOAD(ReturnType, ClassType, func); PYBIND11_OVERRIDE(ReturnType, ClassType, func);
// Version 2: using the PYBIND11_TYPE macro: // Version 2: using the PYBIND11_TYPE macro:
PYBIND11_OVERLOAD(PYBIND11_TYPE(MyReturnType<T1, T2>), PYBIND11_OVERRIDE(PYBIND11_TYPE(MyReturnType<T1, T2>),
PYBIND11_TYPE(Class<T3, T4>), func) PYBIND11_TYPE(Class<T3, T4>), func)
The ``PYBIND11_MAKE_OPAQUE`` macro does *not* require the above workarounds. The ``PYBIND11_MAKE_OPAQUE`` macro does *not* require the above workarounds.
@ -59,7 +59,7 @@ could be realized as follows (important changes highlighted):
/* Acquire GIL before calling Python code */ /* Acquire GIL before calling Python code */
py::gil_scoped_acquire acquire; py::gil_scoped_acquire acquire;
PYBIND11_OVERLOAD_PURE( PYBIND11_OVERRIDE_PURE(
std::string, /* Return type */ std::string, /* Return type */
Animal, /* Parent class */ Animal, /* Parent class */
go, /* Name of function */ go, /* Name of function */

View File

@ -62,6 +62,12 @@ See :ref:`upgrade-guide-2.6` for help upgrading to the new version.
`#2265 <https://github.com/pybind/pybind11/pull/2265>`_ and `#2265 <https://github.com/pybind/pybind11/pull/2265>`_ and
`#2346 <https://github.com/pybind/pybind11/pull/2346>`_ `#2346 <https://github.com/pybind/pybind11/pull/2346>`_
* ``PYBIND11_OVERLOAD*`` macros and ``get_overload`` function replaced by
correctly-named ``PYBIND11_OVERRIDE*`` and ``get_override``, fixing
inconsistencies in the presene of a closing ``;`` in these macros.
``get_type_overload`` is deprecated.
`#2325 <https://github.com/pybind/pybind11/pull/2325>`_
Smaller or developer focused features: Smaller or developer focused features:
* Error now thrown when ``__init__`` is forgotten on subclasses. * Error now thrown when ``__init__`` is forgotten on subclasses.

View File

@ -91,15 +91,15 @@ Inheritance
See :doc:`/classes` and :doc:`/advanced/classes` for more detail. See :doc:`/classes` and :doc:`/advanced/classes` for more detail.
.. doxygendefine:: PYBIND11_OVERLOAD .. doxygendefine:: PYBIND11_OVERRIDE
.. doxygendefine:: PYBIND11_OVERLOAD_PURE .. doxygendefine:: PYBIND11_OVERRIDE_PURE
.. doxygendefine:: PYBIND11_OVERLOAD_NAME .. doxygendefine:: PYBIND11_OVERRIDE_NAME
.. doxygendefine:: PYBIND11_OVERLOAD_PURE_NAME .. doxygendefine:: PYBIND11_OVERRIDE_PURE_NAME
.. doxygenfunction:: get_overload .. doxygenfunction:: get_override
Exceptions Exceptions
========== ==========

View File

@ -21,6 +21,10 @@ If ``__eq__`` defined but not ``__hash__``, ``__hash__`` is now set to
``None``, as in normal CPython. You should add ``__hash__`` if you intended the ``None``, as in normal CPython. You should add ``__hash__`` if you intended the
class to be hashable, possibly using the new ``py::hash`` shortcut. class to be hashable, possibly using the new ``py::hash`` shortcut.
Usage of the ``PYBIND11_OVERLOAD*`` macros and ``get_overload`` function should
be replaced by ``PYBIND11_OVERRIDE*`` and ``get_override``. In the future, the
old macros may be deprecated and removed.
CMake support: CMake support:
-------------- --------------

View File

@ -1797,16 +1797,16 @@ PYBIND11_NAMESPACE_BEGIN(detail)
template <typename T, enable_if_t<!is_pyobject<T>::value, int>> template <typename T, enable_if_t<!is_pyobject<T>::value, int>>
object object_or_cast(T &&o) { return pybind11::cast(std::forward<T>(o)); } object object_or_cast(T &&o) { return pybind11::cast(std::forward<T>(o)); }
struct overload_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the OVERLOAD_INT macro struct override_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the PYBIND11_OVERRIDE_OVERRIDE macro
template <typename ret_type> using overload_caster_t = conditional_t< template <typename ret_type> using override_caster_t = conditional_t<
cast_is_temporary_value_reference<ret_type>::value, make_caster<ret_type>, overload_unused>; cast_is_temporary_value_reference<ret_type>::value, make_caster<ret_type>, override_unused>;
// Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then // Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then
// store the result in the given variable. For other types, this is a no-op. // store the result in the given variable. For other types, this is a no-op.
template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o, make_caster<T> &caster) { template <typename T> enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&o, make_caster<T> &caster) {
return cast_op<T>(load_type(caster, o)); return cast_op<T>(load_type(caster, o));
} }
template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&, overload_unused &) { template <typename T> enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&, override_unused &) {
pybind11_fail("Internal error: cast_ref fallback invoked"); } pybind11_fail("Internal error: cast_ref fallback invoked"); }
// Trampoline use: Having a pybind11::cast with an invalid reference type is going to static_assert, even // Trampoline use: Having a pybind11::cast with an invalid reference type is going to static_assert, even
@ -2222,7 +2222,7 @@ type type::of() {
}} }}
/// Lets you pass a type containing a `,` through a macro parameter without needing a separate /// Lets you pass a type containing a `,` through a macro parameter without needing a separate
/// typedef, e.g.: `PYBIND11_OVERLOAD(PYBIND11_TYPE(ReturnType<A, B>), PYBIND11_TYPE(Parent<C, D>), f, arg)` /// typedef, e.g.: `PYBIND11_OVERRIDE(PYBIND11_TYPE(ReturnType<A, B>), PYBIND11_TYPE(Parent<C, D>), f, arg)`
#define PYBIND11_TYPE(...) __VA_ARGS__ #define PYBIND11_TYPE(...) __VA_ARGS__
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -82,7 +82,7 @@ struct type_equal_to {
template <typename value_type> template <typename value_type>
using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>; using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
struct overload_hash { struct override_hash {
inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const { inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const {
size_t value = std::hash<const void *>()(v.first); size_t value = std::hash<const void *>()(v.first);
value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2);
@ -97,7 +97,7 @@ struct internals {
type_map<type_info *> registered_types_cpp; // std::type_index -> pybind11's type information type_map<type_info *> registered_types_cpp; // std::type_index -> pybind11's type information
std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py; // PyTypeObject* -> base type_info(s) std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py; // PyTypeObject* -> base type_info(s)
std::unordered_multimap<const void *, instance*> registered_instances; // void * -> instance* std::unordered_multimap<const void *, instance*> registered_instances; // void * -> instance*
std::unordered_set<std::pair<const PyObject *, const char *>, overload_hash> inactive_overload_cache; std::unordered_set<std::pair<const PyObject *, const char *>, override_hash> inactive_override_cache;
type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions; type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
std::unordered_map<const PyObject *, std::vector<PyObject *>> patients; std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators; std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;

View File

@ -2110,21 +2110,22 @@ error_already_set::~error_already_set() {
} }
} }
inline function get_type_overload(const void *this_ptr, const detail::type_info *this_type, const char *name) { PYBIND11_NAMESPACE_BEGIN(detail)
handle self = detail::get_object_handle(this_ptr, this_type); inline function get_type_override(const void *this_ptr, const type_info *this_type, const char *name) {
handle self = get_object_handle(this_ptr, this_type);
if (!self) if (!self)
return function(); return function();
handle type = self.get_type(); handle type = self.get_type();
auto key = std::make_pair(type.ptr(), name); auto key = std::make_pair(type.ptr(), name);
/* Cache functions that aren't overloaded in Python to avoid /* Cache functions that aren't overridden in Python to avoid
many costly Python dictionary lookups below */ many costly Python dictionary lookups below */
auto &cache = detail::get_internals().inactive_overload_cache; auto &cache = get_internals().inactive_override_cache;
if (cache.find(key) != cache.end()) if (cache.find(key) != cache.end())
return function(); return function();
function overload = getattr(self, name, function()); function override = getattr(self, name, function());
if (overload.is_cpp_function()) { if (override.is_cpp_function()) {
cache.insert(key); cache.insert(key);
return function(); return function();
} }
@ -2164,34 +2165,36 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
Py_DECREF(result); Py_DECREF(result);
#endif #endif
return overload; return override;
} }
PYBIND11_NAMESPACE_END(detail)
/** \rst /** \rst
Try to retrieve a python method by the provided name from the instance pointed to by the this_ptr. Try to retrieve a python method by the provided name from the instance pointed to by the this_ptr.
:this_ptr: The pointer to the object the overload should be retrieved for. This should be the first :this_ptr: The pointer to the object the overriden method should be retrieved for. This should be
non-trampoline class encountered in the inheritance chain. the first non-trampoline class encountered in the inheritance chain.
:name: The name of the overloaded Python method to retrieve. :name: The name of the overridden Python method to retrieve.
:return: The Python method by this name from the object or an empty function wrapper. :return: The Python method by this name from the object or an empty function wrapper.
\endrst */ \endrst */
template <class T> function get_overload(const T *this_ptr, const char *name) { template <class T> function get_override(const T *this_ptr, const char *name) {
auto tinfo = detail::get_type_info(typeid(T)); auto tinfo = detail::get_type_info(typeid(T));
return tinfo ? get_type_overload(this_ptr, tinfo, name) : function(); return tinfo ? detail::get_type_override(this_ptr, tinfo, name) : function();
} }
#define PYBIND11_OVERLOAD_INT(ret_type, cname, name, ...) { \ #define PYBIND11_OVERRIDE_IMPL(ret_type, cname, name, ...) \
do { \
pybind11::gil_scoped_acquire gil; \ pybind11::gil_scoped_acquire gil; \
pybind11::function overload = pybind11::get_overload(static_cast<const cname *>(this), name); \ pybind11::function override = pybind11::get_override(static_cast<const cname *>(this), name); \
if (overload) { \ if (override) { \
auto o = overload(__VA_ARGS__); \ auto o = override(__VA_ARGS__); \
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) { \ if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) { \
static pybind11::detail::overload_caster_t<ret_type> caster; \ static pybind11::detail::override_caster_t<ret_type> caster; \
return pybind11::detail::cast_ref<ret_type>(std::move(o), caster); \ return pybind11::detail::cast_ref<ret_type>(std::move(o), caster); \
} \ } \
else return pybind11::detail::cast_safe<ret_type>(std::move(o)); \ else return pybind11::detail::cast_safe<ret_type>(std::move(o)); \
} \ } \
} } while (false)
/** \rst /** \rst
Macro to populate the virtual method in the trampoline class. This macro tries to look up a method named 'fn' Macro to populate the virtual method in the trampoline class. This macro tries to look up a method named 'fn'
@ -2202,7 +2205,7 @@ template <class T> function get_overload(const T *this_ptr, const char *name) {
.. code-block:: cpp .. code-block:: cpp
std::string toString() override { std::string toString() override {
PYBIND11_OVERLOAD_NAME( PYBIND11_OVERRIDE_NAME(
std::string, // Return type (ret_type) std::string, // Return type (ret_type)
Animal, // Parent class (cname) Animal, // Parent class (cname)
"__str__", // Name of method in Python (name) "__str__", // Name of method in Python (name)
@ -2210,17 +2213,21 @@ template <class T> function get_overload(const T *this_ptr, const char *name) {
); );
} }
\endrst */ \endrst */
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \ #define PYBIND11_OVERRIDE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \ do { \
return cname::fn(__VA_ARGS__) PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__); \
return cname::fn(__VA_ARGS__); \
} while (false)
/** \rst /** \rst
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD_NAME`, except that it Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERRIDE_NAME`, except that it
throws if no overload can be found. throws if no override can be found.
\endrst */ \endrst */
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \ #define PYBIND11_OVERRIDE_PURE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \ do { \
pybind11::pybind11_fail("Tried to call pure virtual function \"" PYBIND11_STRINGIFY(cname) "::" name "\""); PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__); \
pybind11::pybind11_fail("Tried to call pure virtual function \"" PYBIND11_STRINGIFY(cname) "::" name "\""); \
} while (false)
/** \rst /** \rst
Macro to populate the virtual method in the trampoline class. This macro tries to look up the method Macro to populate the virtual method in the trampoline class. This macro tries to look up the method
@ -2237,7 +2244,7 @@ template <class T> function get_overload(const T *this_ptr, const char *name) {
// Trampoline (need one for each virtual function) // Trampoline (need one for each virtual function)
std::string go(int n_times) override { std::string go(int n_times) override {
PYBIND11_OVERLOAD_PURE( PYBIND11_OVERRIDE_PURE(
std::string, // Return type (ret_type) std::string, // Return type (ret_type)
Animal, // Parent class (cname) Animal, // Parent class (cname)
go, // Name of function in C++ (must match Python name) (fn) go, // Name of function in C++ (must match Python name) (fn)
@ -2246,15 +2253,39 @@ template <class T> function get_overload(const T *this_ptr, const char *name) {
} }
}; };
\endrst */ \endrst */
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \ #define PYBIND11_OVERRIDE(ret_type, cname, fn, ...) \
PYBIND11_OVERLOAD_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__) PYBIND11_OVERRIDE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
/** \rst /** \rst
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD`, except that it throws Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERRIDE`, except that it throws
if no overload can be found. if no override can be found.
\endrst */ \endrst */
#define PYBIND11_OVERRIDE_PURE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
// Deprecated versions
PYBIND11_DEPRECATED("get_type_overload has been deprecated")
inline function get_type_overload(const void *this_ptr, const detail::type_info *this_type, const char *name) {
return detail::get_type_override(this_ptr, this_type, name);
}
template <class T>
inline function get_overload(const T *this_ptr, const char *name) {
return get_override(this_ptr, name);
}
#define PYBIND11_OVERLOAD_INT(ret_type, cname, name, ...) \
PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__)
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERRIDE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, fn, __VA_ARGS__)
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERRIDE_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, fn, __VA_ARGS__);
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), fn, __VA_ARGS__)
#define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \ #define PYBIND11_OVERLOAD_PURE(ret_type, cname, fn, ...) \
PYBIND11_OVERLOAD_PURE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__) PYBIND11_OVERRIDE_PURE(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), fn, __VA_ARGS__);
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -317,7 +317,7 @@ TEST_SUBMODULE(class_, m) {
class TrampolineB : public ProtectedB { class TrampolineB : public ProtectedB {
public: public:
int foo() const override { PYBIND11_OVERLOAD(int, ProtectedB, foo, ); } int foo() const override { PYBIND11_OVERRIDE(int, ProtectedB, foo, ); }
}; };
class PublicistB : public ProtectedB { class PublicistB : public ProtectedB {

View File

@ -30,7 +30,7 @@ private:
class PyWidget final : public Widget { class PyWidget final : public Widget {
using Widget::Widget; using Widget::Widget;
int the_answer() const override { PYBIND11_OVERLOAD_PURE(int, Widget, the_answer); } int the_answer() const override { PYBIND11_OVERRIDE_PURE(int, Widget, the_answer); }
}; };
PYBIND11_EMBEDDED_MODULE(widget_module, m) { PYBIND11_EMBEDDED_MODULE(widget_module, m) {

View File

@ -89,7 +89,7 @@ public:
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); } PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); } PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
virtual ~PyTF6() { print_destroyed(this); } virtual ~PyTF6() { print_destroyed(this); }
int get() override { PYBIND11_OVERLOAD(int, TestFactory6, get, /*no args*/); } int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
}; };
class TestFactory7 { class TestFactory7 {
@ -110,7 +110,7 @@ public:
PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); } PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); } PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
virtual ~PyTF7() { print_destroyed(this); } virtual ~PyTF7() { print_destroyed(this); }
int get() override { PYBIND11_OVERLOAD(int, TestFactory7, get, /*no args*/); } int get() override { PYBIND11_OVERRIDE(int, TestFactory7, get, /*no args*/); }
}; };

View File

@ -22,10 +22,10 @@ public:
class PyVirtClass : public VirtClass { class PyVirtClass : public VirtClass {
void virtual_func() override { void virtual_func() override {
PYBIND11_OVERLOAD(void, VirtClass, virtual_func,); PYBIND11_OVERRIDE(void, VirtClass, virtual_func,);
} }
void pure_virtual_func() override { void pure_virtual_func() override {
PYBIND11_OVERLOAD_PURE(void, VirtClass, pure_virtual_func,); PYBIND11_OVERRIDE_PURE(void, VirtClass, pure_virtual_func,);
} }
}; };

View File

@ -47,7 +47,7 @@ public:
int run(int value) override { int run(int value) override {
/* Generate wrapping code that enables native function overloading */ /* Generate wrapping code that enables native function overloading */
PYBIND11_OVERLOAD( PYBIND11_OVERRIDE(
int, /* Return type */ int, /* Return type */
ExampleVirt, /* Parent class */ ExampleVirt, /* Parent class */
run, /* Name of function */ run, /* Name of function */
@ -56,7 +56,7 @@ public:
} }
bool run_bool() override { bool run_bool() override {
PYBIND11_OVERLOAD_PURE( PYBIND11_OVERRIDE_PURE(
bool, /* Return type */ bool, /* Return type */
ExampleVirt, /* Parent class */ ExampleVirt, /* Parent class */
run_bool, /* Name of function */ run_bool, /* Name of function */
@ -66,7 +66,7 @@ public:
} }
void pure_virtual() override { void pure_virtual() override {
PYBIND11_OVERLOAD_PURE( PYBIND11_OVERRIDE_PURE(
void, /* Return type */ void, /* Return type */
ExampleVirt, /* Parent class */ ExampleVirt, /* Parent class */
pure_virtual, /* Name of function */ pure_virtual, /* Name of function */
@ -78,7 +78,7 @@ public:
// We can return reference types for compatibility with C++ virtual interfaces that do so, but // We can return reference types for compatibility with C++ virtual interfaces that do so, but
// note they have some significant limitations (see the documentation). // note they have some significant limitations (see the documentation).
const std::string &get_string1() override { const std::string &get_string1() override {
PYBIND11_OVERLOAD( PYBIND11_OVERRIDE(
const std::string &, /* Return type */ const std::string &, /* Return type */
ExampleVirt, /* Parent class */ ExampleVirt, /* Parent class */
get_string1, /* Name of function */ get_string1, /* Name of function */
@ -87,7 +87,7 @@ public:
} }
const std::string *get_string2() override { const std::string *get_string2() override {
PYBIND11_OVERLOAD( PYBIND11_OVERRIDE(
const std::string *, /* Return type */ const std::string *, /* Return type */
ExampleVirt, /* Parent class */ ExampleVirt, /* Parent class */
get_string2, /* Name of function */ get_string2, /* Name of function */
@ -141,11 +141,11 @@ public:
class NCVirtTrampoline : public NCVirt { class NCVirtTrampoline : public NCVirt {
#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__) #if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
NonCopyable get_noncopyable(int a, int b) override { NonCopyable get_noncopyable(int a, int b) override {
PYBIND11_OVERLOAD(NonCopyable, NCVirt, get_noncopyable, a, b); PYBIND11_OVERRIDE(NonCopyable, NCVirt, get_noncopyable, a, b);
} }
#endif #endif
Movable get_movable(int a, int b) override { Movable get_movable(int a, int b) override {
PYBIND11_OVERLOAD_PURE(Movable, NCVirt, get_movable, a, b); PYBIND11_OVERRIDE_PURE(Movable, NCVirt, get_movable, a, b);
} }
}; };
@ -159,7 +159,7 @@ struct Base {
struct DispatchIssue : Base { struct DispatchIssue : Base {
virtual std::string dispatch() const { virtual std::string dispatch() const {
PYBIND11_OVERLOAD_PURE(std::string, Base, dispatch, /* no arguments */); PYBIND11_OVERRIDE_PURE(std::string, Base, dispatch, /* no arguments */);
} }
}; };
@ -240,7 +240,7 @@ TEST_SUBMODULE(virtual_functions, m) {
py::print("PyA.f()"); py::print("PyA.f()");
// This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to protect // This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to protect
// a type containing a , // a type containing a ,
PYBIND11_OVERLOAD(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f); PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f);
} }
}; };
@ -265,7 +265,7 @@ TEST_SUBMODULE(virtual_functions, m) {
~PyA2() { py::print("PyA2.~PyA2()"); } ~PyA2() { py::print("PyA2.~PyA2()"); }
void f() override { void f() override {
py::print("PyA2.f()"); py::print("PyA2.f()");
PYBIND11_OVERLOAD(void, A2, f); PYBIND11_OVERRIDE(void, A2, f);
} }
}; };
@ -304,19 +304,19 @@ TEST_SUBMODULE(virtual_functions, m) {
class PyOverrideTest : public OverrideTest { class PyOverrideTest : public OverrideTest {
public: public:
using OverrideTest::OverrideTest; using OverrideTest::OverrideTest;
std::string str_value() override { PYBIND11_OVERLOAD(std::string, OverrideTest, str_value); } std::string str_value() override { PYBIND11_OVERRIDE(std::string, OverrideTest, str_value); }
// Not allowed (uncommenting should hit a static_assert failure): we can't get a reference // Not allowed (uncommenting should hit a static_assert failure): we can't get a reference
// to a python numeric value, since we only copy values in the numeric type caster: // to a python numeric value, since we only copy values in the numeric type caster:
// std::string &str_ref() override { PYBIND11_OVERLOAD(std::string &, OverrideTest, str_ref); } // std::string &str_ref() override { PYBIND11_OVERRIDE(std::string &, OverrideTest, str_ref); }
// But we can work around it like this: // But we can work around it like this:
private: private:
std::string _tmp; std::string _tmp;
std::string str_ref_helper() { PYBIND11_OVERLOAD(std::string, OverrideTest, str_ref); } std::string str_ref_helper() { PYBIND11_OVERRIDE(std::string, OverrideTest, str_ref); }
public: public:
std::string &str_ref() override { return _tmp = str_ref_helper(); } std::string &str_ref() override { return _tmp = str_ref_helper(); }
A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); } A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value); }
A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); } A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref); }
}; };
py::class_<OverrideTest::A>(m, "OverrideTest_A") py::class_<OverrideTest::A>(m, "OverrideTest_A")
@ -393,29 +393,29 @@ class D_Tpl : public C_Tpl { D_METHODS };
class PyA_Repeat : public A_Repeat { class PyA_Repeat : public A_Repeat {
public: public:
using A_Repeat::A_Repeat; using A_Repeat::A_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, A_Repeat, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, A_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, A_Repeat, say_something, times); } std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, A_Repeat, say_something, times); }
}; };
class PyB_Repeat : public B_Repeat { class PyB_Repeat : public B_Repeat {
public: public:
using B_Repeat::B_Repeat; using B_Repeat::B_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, B_Repeat, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE(int, B_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, B_Repeat, say_something, times); } std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, B_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, B_Repeat, lucky_number, ); } double lucky_number() override { PYBIND11_OVERRIDE(double, B_Repeat, lucky_number, ); }
}; };
class PyC_Repeat : public C_Repeat { class PyC_Repeat : public C_Repeat {
public: public:
using C_Repeat::C_Repeat; using C_Repeat::C_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, C_Repeat, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE(int, C_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, C_Repeat, say_something, times); } std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, C_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, C_Repeat, lucky_number, ); } double lucky_number() override { PYBIND11_OVERRIDE(double, C_Repeat, lucky_number, ); }
}; };
class PyD_Repeat : public D_Repeat { class PyD_Repeat : public D_Repeat {
public: public:
using D_Repeat::D_Repeat; using D_Repeat::D_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, D_Repeat, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE(int, D_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, D_Repeat, say_something, times); } std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, D_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, D_Repeat, lucky_number, ); } double lucky_number() override { PYBIND11_OVERRIDE(double, D_Repeat, lucky_number, ); }
}; };
// Inheritance approach 2: templated trampoline classes. // Inheritance approach 2: templated trampoline classes.
@ -436,15 +436,15 @@ template <class Base = A_Tpl>
class PyA_Tpl : public Base { class PyA_Tpl : public Base {
public: public:
using Base::Base; // Inherit constructors using Base::Base; // Inherit constructors
int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, Base, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, Base, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, Base, say_something, times); } std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, Base, say_something, times); }
}; };
template <class Base = B_Tpl> template <class Base = B_Tpl>
class PyB_Tpl : public PyA_Tpl<Base> { class PyB_Tpl : public PyA_Tpl<Base> {
public: public:
using PyA_Tpl<Base>::PyA_Tpl; // Inherit constructors (via PyA_Tpl's inherited constructors) using PyA_Tpl<Base>::PyA_Tpl; // Inherit constructors (via PyA_Tpl's inherited constructors)
int unlucky_number() override { PYBIND11_OVERLOAD(int, Base, unlucky_number, ); } int unlucky_number() override { PYBIND11_OVERRIDE(int, Base, unlucky_number, ); }
double lucky_number() override { PYBIND11_OVERLOAD(double, Base, lucky_number, ); } double lucky_number() override { PYBIND11_OVERRIDE(double, Base, lucky_number, ); }
}; };
// Since C_Tpl and D_Tpl don't declare any new virtual methods, we don't actually need these (we can // Since C_Tpl and D_Tpl don't declare any new virtual methods, we don't actually need these (we can
// use PyB_Tpl<C_Tpl> and PyB_Tpl<D_Tpl> for the trampoline classes instead): // use PyB_Tpl<C_Tpl> and PyB_Tpl<D_Tpl> for the trampoline classes instead):