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
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 */

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
`#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:
* 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.
.. 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
==========

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
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:
--------------

View File

@ -1797,16 +1797,16 @@ PYBIND11_NAMESPACE_BEGIN(detail)
template <typename T, enable_if_t<!is_pyobject<T>::value, int>>
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
template <typename ret_type> using overload_caster_t = conditional_t<
cast_is_temporary_value_reference<ret_type>::value, make_caster<ret_type>, overload_unused>;
struct override_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the PYBIND11_OVERRIDE_OVERRIDE macro
template <typename ret_type> using override_caster_t = conditional_t<
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
// 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) {
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"); }
// 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
/// 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__
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -82,10 +82,10 @@ struct type_equal_to {
template <typename value_type>
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 {
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);
return value;
}
};
@ -97,7 +97,7 @@ struct internals {
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_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;
std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
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) {
handle self = detail::get_object_handle(this_ptr, this_type);
PYBIND11_NAMESPACE_BEGIN(detail)
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)
return function();
handle type = self.get_type();
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 */
auto &cache = detail::get_internals().inactive_overload_cache;
auto &cache = get_internals().inactive_override_cache;
if (cache.find(key) != cache.end())
return function();
function overload = getattr(self, name, function());
if (overload.is_cpp_function()) {
function override = getattr(self, name, function());
if (override.is_cpp_function()) {
cache.insert(key);
return function();
}
@ -2164,34 +2165,36 @@ inline function get_type_overload(const void *this_ptr, const detail::type_info
Py_DECREF(result);
#endif
return overload;
return override;
}
PYBIND11_NAMESPACE_END(detail)
/** \rst
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
non-trampoline class encountered in the inheritance chain.
:name: The name of the overloaded Python method to retrieve.
:this_ptr: The pointer to the object the overriden method should be retrieved for. This should be
the first non-trampoline class encountered in the inheritance chain.
: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.
\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));
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::function overload = pybind11::get_overload(static_cast<const cname *>(this), name); \
if (overload) { \
auto o = overload(__VA_ARGS__); \
pybind11::function override = pybind11::get_override(static_cast<const cname *>(this), name); \
if (override) { \
auto o = override(__VA_ARGS__); \
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); \
} \
else return pybind11::detail::cast_safe<ret_type>(std::move(o)); \
} \
}
} while (false)
/** \rst
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
std::string toString() override {
PYBIND11_OVERLOAD_NAME(
PYBIND11_OVERRIDE_NAME(
std::string, // Return type (ret_type)
Animal, // Parent class (cname)
"__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 */
#define PYBIND11_OVERLOAD_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
return cname::fn(__VA_ARGS__)
#define PYBIND11_OVERRIDE_NAME(ret_type, cname, name, fn, ...) \
do { \
PYBIND11_OVERRIDE_IMPL(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__); \
return cname::fn(__VA_ARGS__); \
} while (false)
/** \rst
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD_NAME`, except that it
throws if no overload can be found.
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERRIDE_NAME`, except that it
throws if no override can be found.
\endrst */
#define PYBIND11_OVERLOAD_PURE_NAME(ret_type, cname, name, fn, ...) \
PYBIND11_OVERLOAD_INT(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), name, __VA_ARGS__) \
pybind11::pybind11_fail("Tried to call pure virtual function \"" PYBIND11_STRINGIFY(cname) "::" name "\"");
#define PYBIND11_OVERRIDE_PURE_NAME(ret_type, cname, name, fn, ...) \
do { \
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
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)
std::string go(int n_times) override {
PYBIND11_OVERLOAD_PURE(
PYBIND11_OVERRIDE_PURE(
std::string, // Return type (ret_type)
Animal, // Parent class (cname)
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 */
#define PYBIND11_OVERLOAD(ret_type, cname, fn, ...) \
PYBIND11_OVERLOAD_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
#define PYBIND11_OVERRIDE(ret_type, cname, fn, ...) \
PYBIND11_OVERRIDE_NAME(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), #fn, fn, __VA_ARGS__)
/** \rst
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERLOAD`, except that it throws
if no overload can be found.
Macro for pure virtual functions, this function is identical to :c:macro:`PYBIND11_OVERRIDE`, except that it throws
if no override can be found.
\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, ...) \
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)

View File

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

View File

@ -30,7 +30,7 @@ private:
class PyWidget final : public 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) {

View File

@ -89,7 +89,7 @@ public:
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
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 {
@ -110,7 +110,7 @@ public:
PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(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 {
void virtual_func() override {
PYBIND11_OVERLOAD(void, VirtClass, virtual_func,);
PYBIND11_OVERRIDE(void, VirtClass, virtual_func,);
}
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 {
/* Generate wrapping code that enables native function overloading */
PYBIND11_OVERLOAD(
PYBIND11_OVERRIDE(
int, /* Return type */
ExampleVirt, /* Parent class */
run, /* Name of function */
@ -56,7 +56,7 @@ public:
}
bool run_bool() override {
PYBIND11_OVERLOAD_PURE(
PYBIND11_OVERRIDE_PURE(
bool, /* Return type */
ExampleVirt, /* Parent class */
run_bool, /* Name of function */
@ -66,7 +66,7 @@ public:
}
void pure_virtual() override {
PYBIND11_OVERLOAD_PURE(
PYBIND11_OVERRIDE_PURE(
void, /* Return type */
ExampleVirt, /* Parent class */
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
// note they have some significant limitations (see the documentation).
const std::string &get_string1() override {
PYBIND11_OVERLOAD(
PYBIND11_OVERRIDE(
const std::string &, /* Return type */
ExampleVirt, /* Parent class */
get_string1, /* Name of function */
@ -87,7 +87,7 @@ public:
}
const std::string *get_string2() override {
PYBIND11_OVERLOAD(
PYBIND11_OVERRIDE(
const std::string *, /* Return type */
ExampleVirt, /* Parent class */
get_string2, /* Name of function */
@ -141,11 +141,11 @@ public:
class NCVirtTrampoline : public NCVirt {
#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
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
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 {
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()");
// This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to protect
// 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()"); }
void f() override {
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 {
public:
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
// 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:
private:
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:
std::string &str_ref() override { return _tmp = str_ref_helper(); }
A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); }
A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); }
A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value); }
A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref); }
};
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 {
public:
using A_Repeat::A_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, A_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, A_Repeat, say_something, times); }
int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, A_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, A_Repeat, say_something, times); }
};
class PyB_Repeat : public B_Repeat {
public:
using B_Repeat::B_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, B_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, B_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, B_Repeat, lucky_number, ); }
int unlucky_number() override { PYBIND11_OVERRIDE(int, B_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, B_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERRIDE(double, B_Repeat, lucky_number, ); }
};
class PyC_Repeat : public C_Repeat {
public:
using C_Repeat::C_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, C_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, C_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, C_Repeat, lucky_number, ); }
int unlucky_number() override { PYBIND11_OVERRIDE(int, C_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, C_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERRIDE(double, C_Repeat, lucky_number, ); }
};
class PyD_Repeat : public D_Repeat {
public:
using D_Repeat::D_Repeat;
int unlucky_number() override { PYBIND11_OVERLOAD(int, D_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, D_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERLOAD(double, D_Repeat, lucky_number, ); }
int unlucky_number() override { PYBIND11_OVERRIDE(int, D_Repeat, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, D_Repeat, say_something, times); }
double lucky_number() override { PYBIND11_OVERRIDE(double, D_Repeat, lucky_number, ); }
};
// Inheritance approach 2: templated trampoline classes.
@ -436,15 +436,15 @@ template <class Base = A_Tpl>
class PyA_Tpl : public Base {
public:
using Base::Base; // Inherit constructors
int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, Base, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, Base, say_something, times); }
int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, Base, unlucky_number, ); }
std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, Base, say_something, times); }
};
template <class Base = B_Tpl>
class PyB_Tpl : public PyA_Tpl<Base> {
public:
using PyA_Tpl<Base>::PyA_Tpl; // Inherit constructors (via PyA_Tpl's inherited constructors)
int unlucky_number() override { PYBIND11_OVERLOAD(int, Base, unlucky_number, ); }
double lucky_number() override { PYBIND11_OVERLOAD(double, Base, lucky_number, ); }
int unlucky_number() override { PYBIND11_OVERRIDE(int, Base, unlucky_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
// use PyB_Tpl<C_Tpl> and PyB_Tpl<D_Tpl> for the trampoline classes instead):