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
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
print(A())
To register the necessary conversion routines, it is necessary to add
a partial overload to the ``pybind11::detail::type_caster<T>`` template.
Although this is an implementation detail, adding partial overloads to this
To register the necessary conversion routines, it is necessary to add an
instantiation of the ``pybind11::detail::type_caster<T>`` template.
Although this is an implementation detail, adding an instantiation of this
type is explicitly allowed.
.. code-block:: cpp

View File

@@ -157,7 +157,7 @@ the declaration
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
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
common header) preceding any usage of ``std::vector<int>``. Opaque types must
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) */
std::string go(int n_times) override {
PYBIND11_OVERLOAD_PURE(
PYBIND11_OVERRIDE_PURE(
std::string, /* Return type */
Animal, /* Parent class */
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
functions, and :c:macro:`PYBIND11_OVERLOAD` should be used for functions which have
The macro :c:macro:`PYBIND11_OVERRIDE_PURE` should be used for pure virtual
functions, and :c:macro:`PYBIND11_OVERRIDE` should be used for functions which have
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
function* slots, which defines the name of function in Python. This is required
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
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.
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
is stored in the referenced Python variable), pybind11 provides one in
the PYBIND11_OVERLOAD macros (when needed) with static storage duration.
Note that this means that invoking the overloaded method on *any*
the PYBIND11_OVERRIDE macros (when needed) with static storage duration.
Note that this means that invoking the overridden method on *any*
instance will change the referenced value stored in *all* instances of
that type.
- Attempts to modify a non-const reference will not have the desired
effect: it will change only the static cache variable, but this change
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::
@@ -237,20 +246,20 @@ override the ``name()`` method):
class PyAnimal : public Animal {
public:
using Animal::Animal; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Animal, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Animal, name, ); }
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Animal, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, Animal, name, ); }
};
class PyDog : public Dog {
public:
using Dog::Dog; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD(std::string, Dog, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Dog, name, ); }
std::string bark() override { PYBIND11_OVERLOAD(std::string, Dog, bark, ); }
std::string go(int n_times) override { PYBIND11_OVERRIDE(std::string, Dog, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, Dog, name, ); }
std::string bark() override { PYBIND11_OVERRIDE(std::string, Dog, bark, ); }
};
.. 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
function that does not take any arguments. For functions that take
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 {
public:
using Husky::Husky; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, Husky, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, Husky, name, ); }
std::string bark() override { PYBIND11_OVERLOAD(std::string, Husky, bark, ); }
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, Husky, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, Husky, name, ); }
std::string bark() override { PYBIND11_OVERRIDE(std::string, Husky, bark, ); }
};
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 {
public:
using AnimalBase::AnimalBase; // Inherit constructors
std::string go(int n_times) override { PYBIND11_OVERLOAD_PURE(std::string, AnimalBase, go, n_times); }
std::string name() override { PYBIND11_OVERLOAD(std::string, AnimalBase, name, ); }
std::string go(int n_times) override { PYBIND11_OVERRIDE_PURE(std::string, AnimalBase, go, n_times); }
std::string name() override { PYBIND11_OVERRIDE(std::string, AnimalBase, name, ); }
};
template <class DogBase = Dog> class PyDog : public PyAnimal<DogBase> {
public:
using PyAnimal<DogBase>::PyAnimal; // Inherit constructors
// 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 bark() override { PYBIND11_OVERLOAD(std::string, DogBase, bark, ); }
std::string go(int n_times) override { PYBIND11_OVERRIDE(std::string, DogBase, go, n_times); }
std::string bark() override { PYBIND11_OVERRIDE(std::string, DogBase, bark, ); }
};
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
except virtual method dispatching, not initializing the trampoline class
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
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
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
methods. Consider for example a C++ method which has the signature
``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)
{
pybind11::gil_scoped_acquire gil; // Acquire the GIL while in this scope.
// Try to look up the overloaded method on the Python side.
pybind11::function overload = pybind11::get_overload(this, "myMethod");
if (overload) { // method is found
auto obj = overload(value); // Call the Python function.
// Try to look up the overridden method on the Python side.
pybind11::function override = pybind11::get_override(this, "myMethod");
if (override) { // method is found
auto obj = override(value); // Call the Python function.
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.
return true; // Return true; value should be used.
@@ -1104,7 +1113,7 @@ described trampoline:
class Trampoline : public A {
public:
int foo() const override { PYBIND11_OVERLOAD(int, A, foo, ); }
int foo() const override { PYBIND11_OVERRIDE(int, A, foo, ); }
};
class Publicist : public A {

View File

@@ -7,14 +7,14 @@ General notes regarding convenience macros
==========================================
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
of types), they *will* get confused by commas in a template argument; for
example, consider:
.. 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
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
using ReturnType = MyReturnType<T1, T2>;
using ClassType = Class<T3, T4>;
PYBIND11_OVERLOAD(ReturnType, ClassType, func);
PYBIND11_OVERRIDE(ReturnType, ClassType, func);
// 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)
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 */
py::gil_scoped_acquire acquire;
PYBIND11_OVERLOAD_PURE(
PYBIND11_OVERRIDE_PURE(
std::string, /* Return type */
Animal, /* Parent class */
go, /* Name of function */