mirror of https://github.com/swig/swig.git
2 Commits
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
ec6354dc34 |
C++20: mix abbreviated function templates with a variadic explicit pack
template<typename... Ts>
std::string f_mix(auto x, Ts... ys);
%template(f_mix_isd) f_mix<int, std::string, double>;
Per [dcl.fct]/19 the invented type template-parameter for each 'auto'
is appended after the explicit template-parameter list, so when the
explicit list ends in a variadic pack the invented sits past the
pack. Previously the %template matcher rejected this with "No
matching function template 'f_mix' found" because the matcher and
the expand machinery assumed the variadic was the last templateparm.
The %template argument list is now bound positionally: leading non-
variadic parameters one to one, the variadic pack absorbs the middle
args, then one trailing arg per 'auto' in declaration order. For the
example above Ts={int, std::string} (pack absorbed) and the trailing
double binds to the invented parm for x, giving the effective wrapper
signature 'f_mix(double x, int y1, std::string y2)'.
Fix details:
- ParmList_find_variadic_parm() finds the variadic anywhere in a parm
list, returning its zero based position. ParmList_variadic_parm()
(last only) is kept for the callers that rightly assume variadic-
last (partial spec parmlists, etc.).
- Swig_cparse_template_locate() (function template branch),
Swig_cparse_template_expand() (variadic substitution range), and
merge_parameters() now find the variadic anywhere and pair the
user's %template args around it: leading non-variadics one to one,
the pack absorbs the middle entries, then trailing non-variadics
(the invented parms) one to one.
- expand_variadic_parms() splices the expanded slice into a function-
parm list at the variadic's actual position, preserving trailing
parms - so 'auto z' may follow the pack in the function signature.
- Each invented parm is marked with abbreviated_auto:1 in
promote_abbreviated_template(). Swig_cparse_template_expand() now
drops trailing invented parms from the emitted C++ template arg
list uniformly across all abbreviated function templates - the C++
compiler deduces the invented type from the wrapper's already-
concrete call argument. Existing abbreviated template wrappers
change cosmetically from 'a_mix<std::string,int>(...)' to
'a_mix<std::string>(...)'; functionally identical.
New tests in Examples/test suite/cpp20_abbreviated_template_mixed.i
add cases f..j: auto before pack, leading explicit + auto + pack,
constrained auto + pack, two autos surrounding a pack (auto after
the pack exercises the function parm list variadic not last path),
and a decorated 'const auto&' with a pack.
Doc updates in CPlusPlus20.html section 10.2.4.
Assisted-by: Claude Opus 4.7
|
|
|
|
b8c3a58ca8 |
C++20: mix abbreviated function templates with explicit template parameter lists; decorated auto
Two related fixes for C++20 abbreviated function templates.
1. Mixing 'auto' parameters with an explicit template parameter list
(e.g. 'template<typename T> T mix(T x, auto y);') used to segfault
'%template' instantiation with an infinite recursion in
cparse_template_expand: the inner cdecl was promoted to a template by
promote_abbreviated_template() and the outer cpp_template_decl rule
then repromoted the same node, leaving 'templatetype' equal to
'template' and the invented parm list orphaned. The fix detects the
already promoted state and merges the explicit parameters with the
invented ones via ParmList_join(). Mixing variadic explicit parms
with an 'auto' parm is documented as not currently %template-
instantiable.
2. Decorated 'auto' parms ('auto&', 'auto*', 'auto&&', 'const auto',
'const auto&', 'Numeric auto&', 'const Numeric auto&') now wrap with
the decoration preserved on the wrapped parameter. New bison rules
in parm_no_dox accept CV-qualifiers before AUTO.
The SwigType encoding for an abbreviated template parm follows the
standard reversed left to right convention: unconstrained 'auto' keeps
the bare 'auto' base, and a constrained 'Concept auto' encodes as an
'auto.' element prefix paired with a 'c(<id>)' base carrying the
concept-id, so 'Numeric auto&' is 'r.auto.c(Numeric)' and 'const Numeric
auto&' is 'r.q(const).auto.c(Numeric)'. promote_abbreviated_template()
reads the concept-id via SwigType_concept_name() and strips the auto
placeholder via SwigType_replace_auto_base().
New tests:
- cpp20_abbreviated_template_mixed exercises plain and constrained
mixings (cases a-e); uses 'std::string' paired with a numeric type
so the binding is observable in the target language.
- cpp20_abbreviated_template_decorated exercises every decorated
'auto' form (cases h-o).
Doc updates in CPlusPlus20.html section 10.2.4 and the SwigType encoding
tables in Doc/Manual/Extending.html and the top of file comments in
Source/Swig/typeobj.c and Source/Swig/stype.c. AGENTS.md tightens the
Changelog guidance to call out that CHANGES.current is user facing only.
Assisted-by: Claude Opus 4.7
|