Merge pull request #226 from dean0x7d/constexpr_arg_check

Check the number of named arguments at compile time
This commit is contained in:
Wenzel Jakob 2016-06-04 01:44:05 +02:00
commit 19d95ef09a
2 changed files with 16 additions and 6 deletions

View File

@ -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(pybind11)

View File

@ -72,6 +72,9 @@ protected:
/// Special internal constructor for functors, lambda functions, etc.
template <typename Func, typename Return, typename... Args, typename... 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; };
/* Store the function including any extra state it might have (e.g. a lambda capture object) */
@ -206,12 +209,6 @@ protected:
}
#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->args.shrink_to_fit();
rec->is_constructor = !strcmp(rec->name, "__init__") || !strcmp(rec->name, "__setstate__");