Make `overload_cast_impl` available in C++11 mode. (#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 #1581: Modify test to use overload_cast_impl, update docs and change log
diff --git a/docs/changelog.rst b/docs/changelog.rst
index f99d351..9576a8b 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -10,7 +10,9 @@
v2.3.1 (Not yet released)
-----------------------------------------------------
-* TBA
+* ``py::details::overload_cast_impl`` is available in C++11 mode, can be used
+ like ``overload_cast`` with an additional set of parantheses.
+ `1581 <https://github.com/pybind/pybind11/pull/1581>`_.
v2.3.0 (June 11, 2019)
-----------------------------------------------------
@@ -105,7 +107,6 @@
`#1744 <https://github.com/pybind/pybind11/pull/1744>`_,
`#1670 <https://github.com/pybind/pybind11/pull/1670>`_.
-
v2.2.4 (September 11, 2018)
-----------------------------------------------------
diff --git a/docs/classes.rst b/docs/classes.rst
index 1deec9b..a63f6a1 100644
--- a/docs/classes.rst
+++ b/docs/classes.rst
@@ -422,6 +422,17 @@
.def("foo_mutable", py::overload_cast<int, float>(&Widget::foo))
.def("foo_const", py::overload_cast<int, float>(&Widget::foo, py::const_));
+If you prefer the ``py::overload_cast`` syntax but have a C++11 compatible compiler only,
+you can use ``py::detail::overload_cast_impl`` with an additional set of parentheses:
+
+.. code-block:: cpp
+
+ template <typename... Args>
+ using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
+
+ py::class_<Pet>(m, "Pet")
+ .def("set", overload_cast_<int>()(&Pet::set), "Set the pet's age")
+ .def("set", overload_cast_<const std::string &>()(&Pet::set), "Set the pet's name");
.. [#cpp14] A compiler which supports the ``-std=c++14`` flag
or Visual Studio 2015 Update 2 and newer.
diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h
index d31be9c..7fb427a 100644
--- a/include/pybind11/detail/common.h
+++ b/include/pybind11/detail/common.h
@@ -720,10 +720,6 @@
/// Dummy destructor wrapper that can be used to expose classes with a private destructor
struct nodelete { template <typename T> void operator()(T*) { } };
-// overload_cast requires variable templates: C++14
-#if defined(PYBIND11_CPP14)
-#define PYBIND11_OVERLOAD_CAST 1
-
NAMESPACE_BEGIN(detail)
template <typename... Args>
struct overload_cast_impl {
@@ -743,19 +739,23 @@
};
NAMESPACE_END(detail)
+// overload_cast requires variable templates: C++14
+#if defined(PYBIND11_CPP14)
+#define PYBIND11_OVERLOAD_CAST 1
/// Syntax sugar for resolving overloaded function pointers:
/// - regular: static_cast<Return (Class::*)(Arg0, Arg1, Arg2)>(&Class::func)
/// - sweet: overload_cast<Arg0, Arg1, Arg2>(&Class::func)
template <typename... Args>
static constexpr detail::overload_cast_impl<Args...> overload_cast = {};
// MSVC 2015 only accepts this particular initialization syntax for this variable template.
+#endif
/// Const member function selector for overload_cast
/// - regular: static_cast<Return (Class::*)(Arg) const>(&Class::func)
/// - sweet: overload_cast<Arg>(&Class::func, const_)
static constexpr auto const_ = std::true_type{};
-#else // no overload_cast: providing something that static_assert-fails:
+#if !defined(PYBIND11_CPP14) // no overload_cast: providing something that static_assert-fails:
template <typename... Args> struct overload_cast {
static_assert(detail::deferred_t<std::false_type, Args...>::value,
"pybind11::overload_cast<...> requires compiling in C++14 mode");
diff --git a/tests/test_methods_and_attributes.cpp b/tests/test_methods_and_attributes.cpp
index fde152b..c7b82f1 100644
--- a/tests/test_methods_and_attributes.cpp
+++ b/tests/test_methods_and_attributes.cpp
@@ -11,6 +11,11 @@
#include "pybind11_tests.h"
#include "constructor_stats.h"
+#if !defined(PYBIND11_OVERLOAD_CAST)
+template <typename... Args>
+using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
+#endif
+
class ExampleMandA {
public:
ExampleMandA() { print_default_created(this); }
@@ -242,15 +247,16 @@
.def("overloaded_const", py::overload_cast<int, int>(&ExampleMandA::overloaded, py::const_))
.def("overloaded_const", py::overload_cast<float, float>(&ExampleMandA::overloaded, py::const_))
#else
- .def("overloaded", static_cast<py::str (ExampleMandA::*)()>(&ExampleMandA::overloaded))
- .def("overloaded", static_cast<py::str (ExampleMandA::*)(int)>(&ExampleMandA::overloaded))
- .def("overloaded", static_cast<py::str (ExampleMandA::*)(int, float)>(&ExampleMandA::overloaded))
+ // Use both the traditional static_cast method and the C++11 compatible overload_cast_
+ .def("overloaded", overload_cast_<>()(&ExampleMandA::overloaded))
+ .def("overloaded", overload_cast_<int>()(&ExampleMandA::overloaded))
+ .def("overloaded", overload_cast_<int, float>()(&ExampleMandA::overloaded))
.def("overloaded", static_cast<py::str (ExampleMandA::*)(float, int)>(&ExampleMandA::overloaded))
.def("overloaded", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded))
.def("overloaded", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
- .def("overloaded_float", static_cast<py::str (ExampleMandA::*)(float, float)>(&ExampleMandA::overloaded))
- .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int ) const>(&ExampleMandA::overloaded))
- .def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, float) const>(&ExampleMandA::overloaded))
+ .def("overloaded_float", overload_cast_<float, float>()(&ExampleMandA::overloaded))
+ .def("overloaded_const", overload_cast_<int >()(&ExampleMandA::overloaded, py::const_))
+ .def("overloaded_const", overload_cast_<int, float>()(&ExampleMandA::overloaded, py::const_))
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, int) const>(&ExampleMandA::overloaded))
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(int, int) const>(&ExampleMandA::overloaded))
.def("overloaded_const", static_cast<py::str (ExampleMandA::*)(float, float) const>(&ExampleMandA::overloaded))