Commit 9e62558d by Dean Moldovan

Check the number of named arguments at compile time

parent e3f8cfcb
...@@ -321,5 +321,18 @@ template <typename... Args> struct process_attributes { ...@@ -321,5 +321,18 @@ template <typename... Args> struct process_attributes {
} }
}; };
/// Compile-time integer sum
constexpr size_t constexpr_sum() { return 0; }
template <typename T, typename... Ts>
constexpr size_t constexpr_sum(T n, Ts... ns) { return n + constexpr_sum(ns...); }
/// Check the number of named arguments at compile time
template <typename... Extra,
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),
size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)>
constexpr bool expected_num_args(size_t nargs) {
return named == 0 || (self + named) == nargs;
}
NAMESPACE_END(detail) NAMESPACE_END(detail)
NAMESPACE_END(pybind11) NAMESPACE_END(pybind11)
...@@ -72,6 +72,9 @@ protected: ...@@ -72,6 +72,9 @@ protected:
/// Special internal constructor for functors, lambda functions, etc. /// Special internal constructor for functors, lambda functions, etc.
template <typename Func, typename Return, typename... Args, typename... Extra> template <typename Func, typename Return, typename... Args, typename... Extra>
void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) { void initialize(Func &&f, Return (*)(Args...), const Extra&... extra) {
static_assert(detail::expected_num_args<Extra...>(sizeof...(Args)),
"The number of named arguments does not match the function signature");
struct capture { typename std::remove_reference<Func>::type f; }; struct capture { typename std::remove_reference<Func>::type f; };
/* Store the function including any extra state it might have (e.g. a lambda capture object) */ /* Store the function including any extra state it might have (e.g. a lambda capture object) */
...@@ -206,12 +209,6 @@ protected: ...@@ -206,12 +209,6 @@ protected:
} }
#endif #endif
if (!rec->args.empty() && (int) rec->args.size() != args)
pybind11_fail(
"cpp_function(): function \"" + std::string(rec->name) + "\" takes " +
std::to_string(args) + " arguments, but " + std::to_string(rec->args.size()) +
" pybind11::arg entries were specified!");
rec->signature = strdup(signature.c_str()); rec->signature = strdup(signature.c_str());
rec->args.shrink_to_fit(); rec->args.shrink_to_fit();
rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__"); rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment