Partial template specializations whose argument is a function type
(eg std::function<RET(ARGS...)>) were not matched: the primary template
was chosen instead.
In Source/CParse/templ.c, does_parm_match and resolve_partial_args now
handle function types by decomposing them with SwigType_pop_function
into a return type and a parameter list, recursing on the return type
and matching the argument list with full support for trailing parameter
packs (v.$N absorbing remaining concrete arguments as a parmlist).
The parmlist match/bind logic shared with the existing template-wrapper
case is factored out into two new helpers, match_partial_parmlists and
resolve_partial_arglists, and the template-wrapper branch is refactored
to use them.
Lib/std/std_function.i is updated to use the standard C++ forward
declaration of std::function, and adds %rename(call) for operator() so
target languages that cannot wrap operator() get a usable name.
Assisted-by: Claude Code (Opus 4.7)
Partial class-template specializations where the specialized argument is
a templated type carrying a parameter pack are now matched and
instantiated correctly for any pack length, including the empty pack:
template <typename...> struct Pack {};
template <typename T> struct Foo {};
template <typename... ARGS> struct Foo<Pack<ARGS...>> { ... };
%template(FooEmpty) Foo<Pack<>>;
%template(FooStr) Foo<Pack<std::string>>;
%template(FooMix) Foo<Pack<int, double>>;
Three changes in Source/CParse/templ.c:
* partial_arg() strips a trailing "v." from a variadic prefix when
extracting the concrete type for a $N partial-spec parameter.
* Swig_cparse_template_expand() iterates over all partial args even
when the template parameter list is shorter (a variadic tparm can
supply multiple args). When the matched tparm is variadic the
resolved type is split into N parms and spliced into templateparms
in place of the variadic placeholder.
* does_parm_match() compares every template parameter pairwise
instead of just the first. A trailing variadic in the partial
pattern absorbs any remaining concrete arguments, and a direct
v.$N partial parameter matches any concrete type. Adds a
null-guard at entry.
New test: cpp11_template_pack_specialization exercises empty,
single- and multi-argument packs.
Assisted-by: Copilot