Skip to content

Commit 19189b4

Browse files
schmeisserwjakob
authored andcommitted
Make overload_cast_impl available in C++11 mode. (pybind#1581)
* Make `overload_cast_impl` available in C++11 mode. Narrow the scope of the `#if defined(PYBIND11_CPP14)` block around overload_cast to only cover the parts where C++14 is stricly required. Thus, the implementation in `pybind11::details::overload_cast_impl` is still available in C++11 mode. * PR pybind#1581: Modify test to use overload_cast_impl, update docs and change log
1 parent 04c8f4b commit 19189b4

File tree

4 files changed

+31
-13
lines changed

4 files changed

+31
-13
lines changed

docs/changelog.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ Starting with version 1.8.0, pybind11 releases use a `semantic versioning
1010
v2.3.1 (Not yet released)
1111
-----------------------------------------------------
1212

13-
* TBA
13+
* ``py::details::overload_cast_impl`` is available in C++11 mode, can be used
14+
like ``overload_cast`` with an additional set of parantheses.
15+
`1581 <https://github.com/pybind/pybind11/pull/1581>`_.
1416

1517
v2.3.0 (June 11, 2019)
1618
-----------------------------------------------------
@@ -105,7 +107,6 @@ v2.3.0 (June 11, 2019)
105107
`#1744 <https://github.com/pybind/pybind11/pull/1744>`_,
106108
`#1670 <https://github.com/pybind/pybind11/pull/1670>`_.
107109

108-
109110
v2.2.4 (September 11, 2018)
110111
-----------------------------------------------------
111112

docs/classes.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,17 @@ on constness, the ``py::const_`` tag should be used:
422422
.def("foo_mutable", py::overload_cast<int, float>(&Widget::foo))
423423
.def("foo_const", py::overload_cast<int, float>(&Widget::foo, py::const_));
424424
425+
If you prefer the ``py::overload_cast`` syntax but have a C++11 compatible compiler only,
426+
you can use ``py::detail::overload_cast_impl`` with an additional set of parentheses:
427+
428+
.. code-block:: cpp
429+
430+
template <typename... Args>
431+
using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
432+
433+
py::class_<Pet>(m, "Pet")
434+
.def("set", overload_cast_<int>()(&Pet::set), "Set the pet's age")
435+
.def("set", overload_cast_<const std::string &>()(&Pet::set), "Set the pet's name");
425436
426437
.. [#cpp14] A compiler which supports the ``-std=c++14`` flag
427438
or Visual Studio 2015 Update 2 and newer.

include/pybind11/detail/common.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,10 +720,6 @@ struct error_scope {
720720
/// Dummy destructor wrapper that can be used to expose classes with a private destructor
721721
struct nodelete { template <typename T> void operator()(T*) { } };
722722

723-
// overload_cast requires variable templates: C++14
724-
#if defined(PYBIND11_CPP14)
725-
#define PYBIND11_OVERLOAD_CAST 1
726-
727723
NAMESPACE_BEGIN(detail)
728724
template <typename... Args>
729725
struct overload_cast_impl {
@@ -743,19 +739,23 @@ struct overload_cast_impl {
743739
};
744740
NAMESPACE_END(detail)
745741

742+
// overload_cast requires variable templates: C++14
743+
#if defined(PYBIND11_CPP14)
744+
#define PYBIND11_OVERLOAD_CAST 1
746745
/// Syntax sugar for resolving overloaded function pointers:
747746
/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func)
748747
/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func)
749748
template <typename... Args>
750749
static constexpr detail::overload_cast_impl<Args...> overload_cast = {};
751750
// MSVC 2015 only accepts this particular initialization syntax for this variable template.
751+
#endif
752752

753753
/// Const member function selector for overload_cast
754754
/// - regular: static_cast<Return (Class::*)(Arg) const>(&Class::func)
755755
/// - sweet: overload_cast<Arg>(&Class::func, const_)
756756
static constexpr auto const_ = std::true_type{};
757757

758-
#else // no overload_cast: providing something that static_assert-fails:
758+
#if !defined(PYBIND11_CPP14) // no overload_cast: providing something that static_assert-fails:
759759
template <typename... Args> struct overload_cast {
760760
static_assert(detail::deferred_t<std::false_type, Args...>::value,
761761
"pybind11::overload_cast<...> requires compiling in C++14 mode");

tests/test_methods_and_attributes.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
#include "pybind11_tests.h"
1212
#include "constructor_stats.h"
1313

14+
#if !defined(PYBIND11_OVERLOAD_CAST)
15+
template <typename... Args>
16+
using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
17+
#endif
18+
1419
class ExampleMandA {
1520
public:
1621
ExampleMandA() { print_default_created(this); }
@@ -242,15 +247,16 @@ TEST_SUBMODULE(methods_and_attributes, m) {
242247
.def("overloaded_const", py::overload_cast<int, int>(&ExampleMandA::overloaded, py::const_))
243248
.def("overloaded_const", py::overload_cast<float, float>(&ExampleMandA::overloaded, py::const_))
244249
#else
245-
.def("overloaded", static_cast<py::str (ExampleMandA::*)()>(&ExampleMandA::overloaded))
246-
.def("overloaded", static_cast<py::str (ExampleMandA::*)(int)>(&ExampleMandA::overloaded))
247-
.def("overloaded", static_cast<py::str (ExampleMandA::*)(int, float)>(&ExampleMandA::overloaded))
250+
// Use both the traditional static_cast method and the C++11 compatible overload_cast_
251+
.def("overloaded", overload_cast_<>()(&ExampleMandA::overloaded))
252+
.def("overloaded", overload_cast_<int>()(&ExampleMandA::overloaded))
253+
.def("overloaded", overload_cast_<int, float>()(&ExampleMandA::overloaded))
248254
.def("overloaded", static_cast<py::str (ExampleMandA::*)(float, int)>(&ExampleMandA::overloaded))
249255
.def("overloaded", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded))
250256
.def("overloaded", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
251-
.def("overloaded_float", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
252-
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int ) const>(&ExampleMandA::overloaded))
253-
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, float) const>(&ExampleMandA::overloaded))
257+
.def("overloaded_float", overload_cast_<float, float>()(&ExampleMandA::overloaded))
258+
.def("overloaded_const", overload_cast_<int >()(&ExampleMandA::overloaded, py::const_))
259+
.def("overloaded_const", overload_cast_<int, float>()(&ExampleMandA::overloaded, py::const_))
254260
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, int) const>(&ExampleMandA::overloaded))
255261
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, int) const>(&ExampleMandA::overloaded))
256262
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, float) const>(&ExampleMandA::overloaded))

0 commit comments

Comments
 (0)