diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 91c9ce753d..d10c989e64 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -15,6 +15,7 @@ #include "detail/descr.h" #include "detail/internals.h" #include +#include #include #include #include @@ -1871,6 +1872,18 @@ struct arg_v : arg { arg_v(const arg &base, T &&x, const char *descr = nullptr) : arg_v(arg(base), std::forward(x), descr) { } +#ifdef PYBIND11_CPP14 +#define ARGV_NAN_DEFAULT_OVERLOAD(FLOAT_TYPE) \ + arg_v(const arg &base, FLOAT_TYPE x) \ + : arg_v(arg(base), x, std::isnan(x) ? "numpy.nan" : nullptr) {} + + ARGV_NAN_DEFAULT_OVERLOAD(float) + ARGV_NAN_DEFAULT_OVERLOAD(double) + ARGV_NAN_DEFAULT_OVERLOAD(long double) + +#undef ARGV_NAN_DEFAULT_OVERLOAD +#endif + /// Same as `arg::noconvert()`, but returns *this as arg_v&, not arg& arg_v &noconvert(bool flag = true) { arg::noconvert(flag); return *this; } diff --git a/tests/test_kwargs_and_defaults.cpp b/tests/test_kwargs_and_defaults.cpp index 8f095fe4a6..c17a0e08e0 100644 --- a/tests/test_kwargs_and_defaults.cpp +++ b/tests/test_kwargs_and_defaults.cpp @@ -13,6 +13,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) { auto kw_func = [](int x, int y) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y); }; + auto kw_func_float = [](float x, double y, long double z) { return "x=" + std::to_string(x) + ", y=" + std::to_string(y) + ", y=" + std::to_string(z); }; // test_named_arguments m.def("kw_func0", kw_func); @@ -33,6 +34,14 @@ TEST_SUBMODULE(kwargs_and_defaults, m) { m.def("kw_func_udl", kw_func, "x"_a, "y"_a=300); m.def("kw_func_udl_z", kw_func, "x"_a, "y"_a=0); + m.def("kw_func_float_123", kw_func_float, "x"_a=1, "y"_a=2, "z"_a=3); +#ifdef PYBIND11_CPP14 + m.def("kw_func_float_nan", kw_func_float, + "x"_a=std::numeric_limits::quiet_NaN(), + "y"_a=std::numeric_limits::quiet_NaN(), + "z"_a=std::numeric_limits::quiet_NaN()); +#endif + // test_args_and_kwargs m.def("args_function", [](py::args args) -> py::tuple { return std::move(args); diff --git a/tests/test_kwargs_and_defaults.py b/tests/test_kwargs_and_defaults.py index bad6636cb4..e61092eca2 100644 --- a/tests/test_kwargs_and_defaults.py +++ b/tests/test_kwargs_and_defaults.py @@ -10,6 +10,11 @@ def test_function_signatures(doc): assert doc(m.kw_func4) == "kw_func4(myList: List[int] = [13, 17]) -> str" assert doc(m.kw_func_udl) == "kw_func_udl(x: int, y: int = 300) -> str" assert doc(m.kw_func_udl_z) == "kw_func_udl_z(x: int, y: int = 0) -> str" + assert doc(m.kw_func_float_123) == "kw_func_float_123(x: float = 1, " \ + "y: float = 2, z: float = 3) -> str" + if hasattr(m, "kw_func_float_nan"): + assert doc(m.kw_func_float_nan) == "kw_func_float_nan(x: float = numpy.nan, " \ + "y: float = numpy.nan, z: float = numpy.nan) -> str" assert doc(m.args_function) == "args_function(*args) -> tuple" assert doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple" assert doc(m.KWClass.foo0) == \