diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index c6abc0e8..e21a9532 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -1248,22 +1248,6 @@ NAMESPACE_BEGIN(detail) // forward declaration struct function_record; -// Helper struct to only allow py::args and/or py::kwargs at the end of the function arguments -template struct assert_args_kwargs_must_be_last { - static constexpr bool has_args = args, has_kwargs = kwargs; - static_assert(args_kwargs_are_last, "py::args/py::kwargs are only permitted as the last argument(s) of a function"); -}; -template struct args_kwargs_must_be_last; -template struct args_kwargs_must_be_last - : args_kwargs_must_be_last {}; -template struct args_kwargs_must_be_last - : assert_args_kwargs_must_be_last {}; -template struct args_kwargs_must_be_last - : assert_args_kwargs_must_be_last {}; -template struct args_kwargs_must_be_last - : assert_args_kwargs_must_be_last {}; -template <> struct args_kwargs_must_be_last<> : assert_args_kwargs_must_be_last {}; - using function_arguments = const std::vector &; /// Helper class which loads arguments for C++ functions called from Python @@ -1271,11 +1255,19 @@ template class argument_loader { using indices = make_index_sequence; - using check_args_kwargs = args_kwargs_must_be_last...>; + template using argument_is_args = std::is_same, args>; + template using argument_is_kwargs = std::is_same, kwargs>; + // Get args/kwargs argument positions relative to the end of the argument list: + static constexpr auto args_pos = constexpr_first() - (int) sizeof...(Args), + kwargs_pos = constexpr_first() - (int) sizeof...(Args); + + static constexpr bool args_kwargs_are_last = kwargs_pos >= - 1 && args_pos >= kwargs_pos - 1; + + static_assert(args_kwargs_are_last, "py::args/py::kwargs are only permitted as the last argument(s) of a function"); public: - static constexpr bool has_kwargs = check_args_kwargs::has_kwargs; - static constexpr bool has_args = check_args_kwargs::has_args; + static constexpr bool has_kwargs = kwargs_pos < 0; + static constexpr bool has_args = args_pos < 0; static PYBIND11_DESCR arg_names() { return detail::concat(make_caster::name()...); }