From d65e34d61d5f49ffbe7c2e7864391366f1124b0e Mon Sep 17 00:00:00 2001 From: Yannick Jadoul Date: Tue, 15 Sep 2020 14:56:20 +0200 Subject: [PATCH] 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 --- docs/advanced/cast/custom.rst | 6 +- docs/advanced/cast/stl.rst | 2 +- docs/advanced/classes.rst | 65 ++++++++++-------- docs/advanced/misc.rst | 10 +-- docs/changelog.rst | 6 ++ docs/reference.rst | 10 +-- docs/upgrade.rst | 4 ++ include/pybind11/cast.h | 10 +-- include/pybind11/detail/internals.h | 6 +- include/pybind11/pybind11.h | 97 ++++++++++++++++++--------- tests/test_class.cpp | 2 +- tests/test_embed/test_interpreter.cpp | 2 +- tests/test_factory_constructors.cpp | 4 +- tests/test_gil_scoped.cpp | 4 +- tests/test_virtual_functions.cpp | 60 ++++++++--------- 15 files changed, 169 insertions(+), 119 deletions(-) diff --git a/docs/advanced/cast/custom.rst b/docs/advanced/cast/custom.rst index e4f99ac5b..a779444c2 100644 --- a/docs/advanced/cast/custom.rst +++ b/docs/advanced/cast/custom.rst @@ -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`` 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`` template. +Although this is an implementation detail, adding an instantiation of this type is explicitly allowed. .. code-block:: cpp diff --git a/docs/advanced/cast/stl.rst b/docs/advanced/cast/stl.rst index e48409f02..7f708b81e 100644 --- a/docs/advanced/cast/stl.rst +++ b/docs/advanced/cast/stl.rst @@ -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``. Opaque types must also have a corresponding ``class_`` declaration to associate them with a name diff --git a/docs/advanced/classes.rst b/docs/advanced/classes.rst index b91e8a1fc..82812069b 100644 --- a/docs/advanced/classes.rst +++ b/docs/advanced/classes.rst @@ -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 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 PyDog : public PyAnimal { public: using PyAnimal::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(obj)) { // check if it returned a Python integer type value = obj.cast(); // 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 { diff --git a/docs/advanced/misc.rst b/docs/advanced/misc.rst index 8342210bc..a5899c67a 100644 --- a/docs/advanced/misc.rst +++ b/docs/advanced/misc.rst @@ -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, Class, func) + PYBIND11_OVERRIDE(MyReturnType, Class, 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; using ClassType = Class; - PYBIND11_OVERLOAD(ReturnType, ClassType, func); + PYBIND11_OVERRIDE(ReturnType, ClassType, func); // Version 2: using the PYBIND11_TYPE macro: - PYBIND11_OVERLOAD(PYBIND11_TYPE(MyReturnType), + PYBIND11_OVERRIDE(PYBIND11_TYPE(MyReturnType), PYBIND11_TYPE(Class), 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 */ diff --git a/docs/changelog.rst b/docs/changelog.rst index 77fd44173..354604003 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -62,6 +62,12 @@ See :ref:`upgrade-guide-2.6` for help upgrading to the new version. `#2265 `_ and `#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 `_ + Smaller or developer focused features: * Error now thrown when ``__init__`` is forgotten on subclasses. diff --git a/docs/reference.rst b/docs/reference.rst index a9fbe6001..752dfed2d 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -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 ========== diff --git a/docs/upgrade.rst b/docs/upgrade.rst index 894c65fdc..502ce76ee 100644 --- a/docs/upgrade.rst +++ b/docs/upgrade.rst @@ -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: -------------- diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 5601f2ec8..c588bd2f3 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1797,16 +1797,16 @@ PYBIND11_NAMESPACE_BEGIN(detail) template ::value, int>> object object_or_cast(T &&o) { return pybind11::cast(std::forward(o)); } -struct overload_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the OVERLOAD_INT macro -template using overload_caster_t = conditional_t< - cast_is_temporary_value_reference::value, make_caster, overload_unused>; +struct override_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the PYBIND11_OVERRIDE_OVERRIDE macro +template using override_caster_t = conditional_t< + cast_is_temporary_value_reference::value, make_caster, 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 enable_if_t::value, T> cast_ref(object &&o, make_caster &caster) { return cast_op(load_type(caster, o)); } -template enable_if_t::value, T> cast_ref(object &&, overload_unused &) { +template enable_if_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), PYBIND11_TYPE(Parent), f, arg)` +/// typedef, e.g.: `PYBIND11_OVERRIDE(PYBIND11_TYPE(ReturnType), PYBIND11_TYPE(Parent), f, arg)` #define PYBIND11_TYPE(...) __VA_ARGS__ PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/internals.h b/include/pybind11/detail/internals.h index cf40e9fe9..133d2f4c8 100644 --- a/include/pybind11/detail/internals.h +++ b/include/pybind11/detail/internals.h @@ -82,10 +82,10 @@ struct type_equal_to { template using type_map = std::unordered_map; -struct overload_hash { +struct override_hash { inline size_t operator()(const std::pair& v) const { size_t value = std::hash()(v.first); - value ^= std::hash()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); + value ^= std::hash()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2); return value; } }; @@ -97,7 +97,7 @@ struct internals { type_map registered_types_cpp; // std::type_index -> pybind11's type information std::unordered_map> registered_types_py; // PyTypeObject* -> base type_info(s) std::unordered_multimap registered_instances; // void * -> instance* - std::unordered_set, overload_hash> inactive_overload_cache; + std::unordered_set, override_hash> inactive_override_cache; type_map> direct_conversions; std::unordered_map> patients; std::forward_list registered_exception_translators; diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 602d5790a..866a62dc0 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -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 function get_overload(const T *this_ptr, const char *name) { +template 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(this), name); \ - if (overload) { \ - auto o = overload(__VA_ARGS__); \ + pybind11::function override = pybind11::get_override(static_cast(this), name); \ + if (override) { \ + auto o = override(__VA_ARGS__); \ if (pybind11::detail::cast_is_temporary_value_reference::value) { \ - static pybind11::detail::overload_caster_t caster; \ + static pybind11::detail::override_caster_t caster; \ return pybind11::detail::cast_ref(std::move(o), caster); \ } \ else return pybind11::detail::cast_safe(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 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 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 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 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 +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) diff --git a/tests/test_class.cpp b/tests/test_class.cpp index b7d52a1b5..e7eaa83ea 100644 --- a/tests/test_class.cpp +++ b/tests/test_class.cpp @@ -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 { diff --git a/tests/test_embed/test_interpreter.cpp b/tests/test_embed/test_interpreter.cpp index 222bd565f..753ce54dc 100644 --- a/tests/test_embed/test_interpreter.cpp +++ b/tests/test_embed/test_interpreter.cpp @@ -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) { diff --git a/tests/test_factory_constructors.cpp b/tests/test_factory_constructors.cpp index f61474346..f70ed3335 100644 --- a/tests/test_factory_constructors.cpp +++ b/tests/test_factory_constructors.cpp @@ -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*/); } }; diff --git a/tests/test_gil_scoped.cpp b/tests/test_gil_scoped.cpp index dc9b7ed22..eb6308956 100644 --- a/tests/test_gil_scoped.cpp +++ b/tests/test_gil_scoped.cpp @@ -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,); } }; diff --git a/tests/test_virtual_functions.cpp b/tests/test_virtual_functions.cpp index c5ee6365f..0210695e2 100644 --- a/tests/test_virtual_functions.cpp +++ b/tests/test_virtual_functions.cpp @@ -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::type), A, f); + PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if::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_(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 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 PyB_Tpl : public PyA_Tpl { public: using PyA_Tpl::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 and PyB_Tpl for the trampoline classes instead):