summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2023-01-30 08:22:33 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2023-02-17 08:24:25 +0000
commit817c700ced95b2fc615e1619c89fcec21f66af55 (patch)
treec1fc9e77a50ce32657b5f7754e40edcc3ec2cf7a /Source
parentbd2de6fc0604a9990dd70c2603004d3062842d9e (diff)
downloadswig-817c700ced95b2fc615e1619c89fcec21f66af55.tar.gz
Template partial specialization improvements
Closes #1300 Changes to support the first example below (partial specialization of template parameter types like Vect<int>). Previous implementation and design could only handle one template parameter name per template specialization argument, such as Vect<TS> for the first template specialization argument (for first example below) template<class TS, typename TTS> class Foo<Vect<TS>, int> { ... }; and not template<class TS, typename TTS> class Foo<Vect<TS, TTS>, int> { ... }; New approach is to not modify 'templateparms' in the template node, (except to fill in default args from primary template) Previous implementation also assumed a template parameter could not be used more than once in the specialized arguments, such as template<typename T> struct Hey<T, T> { void specialA() {} }; Examples ======== 1) For primary: template<class T, typename TT> class Foo { ... }; and specialization: template<class TS, typename TTS> class Foo<Vect<TS>, TTS> { ... }; Fix specialization template from (wrong) | templateparms - 'Vect< TS >,typename TTS' to (correct/new way) | templateparms - 'class TS,typename TTS' 2) For primary: template<typename P1 = int, typename P2 = double> struct Partialler { void primary(P1, P2) {}; }; and specialization: template<typename S1, typename S2> struct Partialler<S2, S1*> { void special(S1*, S2, bool) {}; }; Specialized template changes from (wrong) | templateparms - 'typename S2=int,typename S1=double' to (correct/new way, default args are removed) | templateparms - 'typename S1,typename S2' and subsequent change to partialargs from | partialargs - "Partialler<($1,p.$2)>" to | partialargs - "Partialler<($2,p.$1)>" so that the $n number is now more logically the nth template parameter in templateparms 3) For primary: template<typename X, typename Y> struct Hey { void primary() {} }; and specialization: template<typename T> struct Hey<T, T> { void specialA() {} }; old (wrong/old way) | templateparms - 'typename T,typename T' new (correct/new way) | templateparms - 'typename T' These are unchanged and are okay: | partialargs - "Hey<($1,$1)>" 4) For primary: enum Hello { hi, hello }; template <Hello, class A> struct C {}; and specialization: template <class A> struct C<hello,A> { ... }; old (wrong/old way) | templateparms - 'hello,class A' new (correct/new way) | templateparms - 'class A' and subsequent changes to partialargs from | partialargs - "C<(hi,$2)>" to | partialargs - "C<(hi,$1)>" Test-suite ========== Identical output as before in Python but in Java, an unimportant change in cpp11_variadic_function_templates.i results in one variadic parameter name being different. New testcase template_partial_specialization_more.i with more testcases added including above examples that are not already in the test-suite.
Diffstat (limited to 'Source')
-rw-r--r--Source/CParse/cparse.h2
-rw-r--r--Source/CParse/parser.y105
-rw-r--r--Source/CParse/templ.c251
3 files changed, 188 insertions, 170 deletions
diff --git a/Source/CParse/cparse.h b/Source/CParse/cparse.h
index 039e97de7..db050eb91 100644
--- a/Source/CParse/cparse.h
+++ b/Source/CParse/cparse.h
@@ -68,7 +68,7 @@ extern "C" {
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
extern Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
extern void Swig_cparse_debug_templates(int);
- extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary);
+ extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary, Node *templ);
#ifdef __cplusplus
}
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index c66b60db6..df2a87a91 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -2883,7 +2883,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
Node *primary_template = Swig_symbol_clookup(tname, 0);
/* Expand the template */
- ParmList *temparms = Swig_cparse_template_parms_expand($7, primary_template);
+ ParmList *temparms = Swig_cparse_template_parms_expand($7, primary_template, nn);
templnode = copy_node(nn);
update_nested_classes(templnode); /* update classes nested within template */
@@ -4128,112 +4128,32 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
if (!Getattr($$,"sym:weak")) {
Setattr($$,"sym:typename","1");
}
+ Setattr($$, "primarytemplate", tempn);
+ Setattr($$, "templateparms", $3);
+ Delattr($$, "specialization");
+ Setattr($$, "partialspecialization", "1");
if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) {
Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms")));
} else {
-
- /* This code builds the argument list for the partial template
- specialization. This is a little hairy, but the idea is as
- follows:
-
- $3 contains a list of arguments supplied for the template.
- For example template<class T>.
-
- tlist is a list of the specialization arguments--which may be
- different. For example class<int,T>.
-
- tp is a copy of the arguments in the original template definition.
-
- The patching algorithm walks through the list of supplied
- arguments ($3), finds the position in the specialization arguments
- (tlist), and then patches the name in the argument list of the
- original template.
- */
-
- {
- String *pn;
- Parm *p, *p1;
- int i, nargs;
- Parm *tp = CopyParmList(Getattr(tempn,"templateparms"));
- nargs = Len(tlist);
- p = $3;
- while (p) {
- for (i = 0; i < nargs; i++){
- pn = Getattr(p,"name");
- if (Strcmp(pn,SwigType_base(Getitem(tlist,i))) == 0) {
- int j;
- Parm *p1 = tp;
- for (j = 0; j < i; j++) {
- p1 = nextSibling(p1);
- }
- Setattr(p1,"name",pn);
- Setattr(p1,"partialarg","1");
- }
- }
- p = nextSibling(p);
- }
- p1 = tp;
- i = 0;
- while (p1) {
- if (!Getattr(p1,"partialarg")) {
- Delattr(p1,"name");
- Setattr(p1,"type", Getitem(tlist,i));
- }
- i++;
- p1 = nextSibling(p1);
- }
- Setattr($$,"templateparms",tp);
- Delete(tp);
- }
- #if 0
- /* Patch the parameter list */
- if (tempn) {
- Parm *p,*p1;
- ParmList *tp = CopyParmList(Getattr(tempn,"templateparms"));
- p = $3;
- p1 = tp;
- while (p && p1) {
- String *pn = Getattr(p,"name");
- Printf(stdout,"pn = '%s'\n", pn);
- if (pn) Setattr(p1,"name",pn);
- else Delattr(p1,"name");
- pn = Getattr(p,"type");
- if (pn) Setattr(p1,"type",pn);
- p = nextSibling(p);
- p1 = nextSibling(p1);
- }
- Setattr($$,"templateparms",tp);
- Delete(tp);
- } else {
- Setattr($$,"templateparms",$3);
- }
- #endif
- Delattr($$,"specialization");
- Setattr($$,"partialspecialization","1");
- /* Create a specialized name for matching */
- {
+ /* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
Parm *p = $3;
String *fname = NewString(Getattr($$,"name"));
String *ffname = 0;
ParmList *partialparms = 0;
char tmp[32];
- int i, ilen;
+ int i = 0;
while (p) {
- String *n = Getattr(p,"name");
- if (!n) {
+ String *name = Getattr(p,"name");
+ ++i;
+ if (!name) {
p = nextSibling(p);
continue;
}
- ilen = Len(tlist);
- for (i = 0; i < ilen; i++) {
- if (Strstr(Getitem(tlist,i),n)) {
- sprintf(tmp,"$%d",i+1);
- Replaceid(fname,n,tmp);
- }
- }
+ sprintf(tmp, "$%d", i);
+ Replaceid(fname, name, tmp);
p = nextSibling(p);
}
/* Patch argument names with typedef */
@@ -4279,7 +4199,6 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
Setattr($$,"partialargs",ffname);
Swig_symbol_cadd(ffname,$$);
}
- }
Delete(tlist);
Delete(targs);
} else {
diff --git a/Source/CParse/templ.c b/Source/CParse/templ.c
index 7a4d0cf4f..a126ad29c 100644
--- a/Source/CParse/templ.c
+++ b/Source/CParse/templ.c
@@ -13,6 +13,7 @@
#include "swig.h"
#include "cparse.h"
+#include <ctype.h>
static int template_debug = 0;
@@ -396,25 +397,43 @@ static void cparse_postprocess_expanded_template(Node *n) {
/* -----------------------------------------------------------------------------
* partial_arg()
+ *
+ * Return a parameter with type that matches the specialized template argument.
+ * If the input has no partial type, the name is not set in the returned parameter.
+ *
+ * type: an instantiated template parameter type, for example: Vect<(int)>
+ * partialtype: type from specialized template where parameter name has been
+ * replaced by a $ variable, for example: Vect<($1)>
+ *
+ * Returns a parameter of type 'int' and name $1 for the two example parameters above.
* ----------------------------------------------------------------------------- */
-static String *partial_arg(String *s, String *p) {
- char *c;
- char *cp = Char(p);
- String *prefix;
- String *newarg;
-
- /* Find the prefix on the partial argument */
-
- c = strchr(cp, '$');
- if (!c) {
- return Copy(s);
+static Parm *partial_arg(const SwigType *type, const SwigType *partialtype) {
+ SwigType *parmtype;
+ String *parmname = 0;
+ const char *cp = Char(partialtype);
+ const char *c = strchr(cp, '$');
+
+ if (c) {
+ int suffix_length;
+ int prefix_length = c - cp;
+ int type_length = Len(type);
+ const char *suffix = c;
+ String *prefix = NewStringWithSize(cp, prefix_length);
+ while (++suffix) {
+ if (!isdigit((int)*suffix))
+ break;
+ }
+ parmname = NewStringWithSize(c, suffix - c); /* $1, $2 etc */
+ suffix_length = strlen(suffix);
+ assert(Strstr(type, prefix) == Char(type)); /* check that the start of both types match */
+ assert(strcmp(Char(type) + type_length - suffix_length, suffix) == 0); /* check that the end of both types match */
+ parmtype = NewStringWithSize(Char(type) + prefix_length, type_length - suffix_length - prefix_length);
+ Delete(prefix);
+ } else {
+ parmtype = Copy(type);
}
- prefix = NewStringWithSize(cp, (int)(c - cp));
- newarg = Copy(s);
- Replace(newarg, prefix, "", DOH_REPLACE_FIRST);
- Delete(prefix);
- return newarg;
+ return NewParmWithoutFileLineInfo(parmtype, parmname);
}
/* -----------------------------------------------------------------------------
@@ -429,6 +448,8 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
String *tbase;
Parm *unexpanded_variadic_parm = 0;
ParmList *expanded_variadic_parms = 0;
+ ParmList *templateparms = Getattr(n, "templateparms");
+ ParmList *templateparmsraw = 0;
patchlist = NewList(); /* List of String * ("name" and "value" attributes) */
cpatchlist = NewList(); /* List of String * (code) */
typelist = NewList(); /* List of SwigType * types */
@@ -439,12 +460,13 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
tname = Copy(Getattr(n, "name"));
tbase = Swig_scopename_last(tname);
- /* Look for partial specialization matching */
if (Getattr(n, "partialargs")) {
+ /* Partial specialization */
Parm *p, *tp;
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
p = ptargs;
tp = tparms;
+ /* Adjust templateparms so that the type is expanded, eg typename => int */
while (p && tp) {
SwigType *ptype;
SwigType *tptype;
@@ -453,9 +475,20 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
tptype = Getattr(tp, "type");
if (ptype && tptype) {
SwigType *ty = Swig_symbol_typedef_reduce(tptype, tscope);
- partial_type = partial_arg(ty, ptype);
+ Parm *partial_parm = partial_arg(ty, ptype);
+ String *partial_name = Getattr(partial_parm, "name");
+ partial_type = Copy(Getattr(partial_parm, "type"));
/* Printf(stdout,"partial '%s' '%s' ---> '%s'\n", tptype, ptype, partial_type); */
- Setattr(tp, "type", partial_type);
+ if (partial_name && strchr(Char(partial_name), '$') == Char(partial_name)) {
+ int index = atoi(Char(partial_name) + 1) - 1;
+ assert(index >= 0);
+ Parm *parm = ParmList_nth_parm(templateparms, index);
+ assert(parm);
+ if (parm) {
+ Setattr(parm, "type", partial_type);
+ }
+ }
+ Delete(partial_parm);
Delete(partial_type);
Delete(ty);
}
@@ -464,20 +497,17 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
}
assert(ParmList_len(ptargs) == ParmList_len(tparms));
Delete(ptargs);
+ } else {
+ Setattr(n, "templateparmsraw", Getattr(n, "templateparms"));
+ templateparms = CopyParmList(tparms);
+ Setattr(n, "templateparms", templateparms);
}
- /*
- Parm *p = tparms;
- while (p) {
- Printf(stdout, "tparm: '%s' '%s' '%s'\n", Getattr(p, "name"), Getattr(p, "type"), Getattr(p, "value"));
- p = nextSibling(p);
- }
- */
-
- ParmList *templateparms = Getattr(n, "templateparms");
- unexpanded_variadic_parm = ParmList_variadic_parm(templateparms);
+ /* TODO: variadic parms for partially specialized templates */
+ templateparmsraw = Getattr(n, "templateparmsraw");
+ unexpanded_variadic_parm = ParmList_variadic_parm(templateparmsraw);
if (unexpanded_variadic_parm)
- expanded_variadic_parms = ParmList_nth_parm(tparms, ParmList_len(templateparms) - 1);
+ expanded_variadic_parms = ParmList_nth_parm(templateparms, ParmList_len(templateparmsraw) - 1);
/* Printf(stdout,"targs = '%s'\n", templateargs);
Printf(stdout,"rname = '%s'\n", rname);
@@ -496,24 +526,23 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
/* Patch all of the types */
{
Parm *tp = Getattr(n, "templateparms");
- Parm *p = tparms;
/* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
- if (p && tp) {
+ if (tp) {
Symtab *tsdecl = Getattr(n, "sym:symtab");
String *tsname = Getattr(n, "sym:name");
- while (p && tp) {
+ while (tp) {
String *name, *value, *valuestr, *tmp, *tmpr;
int sz, i;
String *dvalue = 0;
String *qvalue = 0;
name = Getattr(tp, "name");
- value = Getattr(p, "value");
+ value = Getattr(tp, "value");
if (name) {
if (!value)
- value = Getattr(p, "type");
+ value = Getattr(tp, "type");
qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
if (SwigType_istemplate(dvalue)) {
@@ -524,17 +553,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
assert(dvalue);
valuestr = SwigType_str(dvalue, 0);
- /* Need to patch default arguments */
- {
- Parm *rp = nextSibling(p);
- while (rp) {
- String *rvalue = Getattr(rp, "value");
- if (rvalue) {
- Replace(rvalue, name, dvalue, DOH_REPLACE_ID);
- }
- rp = nextSibling(rp);
- }
- }
sz = Len(patchlist);
for (i = 0; i < sz; i++) {
String *s = Getitem(patchlist, i);
@@ -580,10 +598,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
Delete(dvalue);
Delete(qvalue);
}
- p = nextSibling(p);
tp = nextSibling(tp);
- if (!p)
- p = tp;
}
} else {
/* No template parameters at all. This could be a specialization */
@@ -626,25 +641,46 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch;
/* -----------------------------------------------------------------------------
+ * is_exact_partial_type()
+ *
+ * Return 1 if parm matches $1, $2, $3 etc exactly without any other prefixes or
+ * suffixes. Return 0 otherwise.
+ * ----------------------------------------------------------------------------- */
+
+static int is_exact_partial_type(const SwigType *type) {
+ const char *c = Char(type);
+ int is_exact = 0;
+ if (*c == '$' && isdigit((int)*(c + 1))) {
+ const char *suffix = c + 1;
+ while (++suffix) {
+ if (!isdigit((int)*suffix))
+ break;
+ }
+ is_exact = (*suffix == 0);
+ }
+ return is_exact;
+}
+
+/* -----------------------------------------------------------------------------
* does_parm_match()
*
- * Template argument deduction - check if a template type matches a partially specialized
+ * Template argument deduction - check if a template type matches a partially specialized
* template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'.
*
* type - template parameter type to match against
* partial_parm_type - specialized template type, for example, r.$1 (partially specialized) or r.int (fully specialized)
- * partial_parm - partially specialized template parameter name, such as, $1 or $2 or $3, etc
* tscope - template scope
- * specialization_priority - (output) contains a value indicating how good the match is
+ * specialization_priority - (output) contains a value indicating how good the match is
* (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch.
* ----------------------------------------------------------------------------- */
-static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm, Symtab *tscope, int *specialization_priority) {
+static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, Symtab *tscope, int *specialization_priority) {
static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */
+ static const int TEMPLATE_MATCH_PRIORITY = 1000; /* a priority added for each nested template, assumes max length of any prefix, such as r.q(const). , is less than this number */
SwigType *ty = Swig_symbol_typedef_reduce(type, tscope);
SwigType *pp_prefix = SwigType_prefix(partial_parm_type);
int pp_len = Len(pp_prefix);
- EMatch match = Strstr(partial_parm_type, partial_parm) == 0 ? ExactNoMatch : PartiallySpecializedNoMatch;
+ EMatch match = Strchr(partial_parm_type, '$') == 0 ? ExactNoMatch : PartiallySpecializedNoMatch;
*specialization_priority = -1;
if (Equal(ty, partial_parm_type)) {
@@ -653,27 +689,89 @@ static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const
} else if (match == PartiallySpecializedNoMatch) {
if ((pp_len > 0 && Strncmp(ty, pp_prefix, pp_len) == 0)) {
/*
- type starts with pp_prefix, so it is a partial specialization type match, for example,
+ Type starts with pp_prefix, so it is a partial specialization type match, for example,
all of the following could match the type in the %template:
- template <typename T> struct XX {};
- template <typename T> struct XX<T &> {}; // r.$1
- template <typename T> struct XX<T const&> {}; // r.q(const).$1
- template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
- %template(XXX) XX<int *const&>; // r.q(const).p.int
-
+ template <typename T> struct XX {};
+ template <typename T> struct XX<T &> {}; // r.$1
+ template <typename T> struct XX<T const&> {}; // r.q(const).$1
+ template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
+ %template(XXX) XX<int *const&>; // r.q(const).p.int
where type="r.q(const).p.int" will match either of pp_prefix="r.", pp_prefix="r.q(const)." pp_prefix="r.q(const).p."
*/
match = PartiallySpecializedMatch;
*specialization_priority = pp_len;
- } else if (pp_len == 0 && Equal(partial_parm_type, partial_parm)) {
+ } else if (pp_len == 0 && is_exact_partial_type(partial_parm_type)) {
/*
- type without a prefix match, as in $1 for int
- template <typename T, typename U> struct XX {};
- template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2
- %template(XXX) XX<int, double&>; // int,r.double
+ Type without a prefix match, as in $1 for int
+ template <typename T, typename U> struct XX {};
+ template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2
+ %template(XXX) XX<int, double&>; // int,r.double
*/
match = PartiallySpecializedMatch;
*specialization_priority = pp_len;
+ } else {
+ /*
+ Check for template types that are templates such as
+ template<typename V> struct Vect {};
+ template<typename T> class XX {};
+ template<class TT> class XX<Vect<TT>> {};
+ %template(XXVectInt) XX<Vect<int>>;
+ matches type="Vect<(int)>" and partial_parm_type="Vect<($1)>"
+ */
+ if (SwigType_istemplate(partial_parm_type) && SwigType_istemplate(ty)) {
+
+ SwigType *qt = Swig_symbol_typedef_reduce(ty, tscope);
+ String *tsuffix = SwigType_templatesuffix(qt);
+
+ SwigType *pp_qt = Swig_symbol_typedef_reduce(partial_parm_type, tscope);
+ String *pp_tsuffix = SwigType_templatesuffix(pp_qt);
+
+ if (Equal(tsuffix, pp_tsuffix) && Len(tsuffix) == 0) {
+ String *tprefix = SwigType_templateprefix(qt);
+ String *qprefix = SwigType_typedef_qualified(tprefix);
+
+ String *pp_tprefix = SwigType_templateprefix(pp_qt);
+ String *pp_qprefix = SwigType_typedef_qualified(pp_tprefix);
+
+ if (Equal(qprefix, pp_qprefix)) {
+ String *templateargs = SwigType_templateargs(qt);
+ List *parms = SwigType_parmlist(templateargs);
+ Iterator pi = First(parms);
+ Parm *p = pi.item;
+
+ String *pp_templateargs = SwigType_templateargs(pp_qt);
+ List *pp_parms = SwigType_parmlist(pp_templateargs);
+ Iterator pp_pi = First(pp_parms);
+ Parm *pp = pp_pi.item;
+
+ if (p && pp) {
+ /* Implementation is limited to matching single parameter templates only for now */
+ int priority;
+ match = does_parm_match(p, pp, tscope, &priority);
+ if (match <= PartiallySpecializedNoMatch) {
+ *specialization_priority = priority;
+ } else {
+ *specialization_priority = priority + TEMPLATE_MATCH_PRIORITY;
+ }
+ }
+
+ Delete(pp_parms);
+ Delete(pp_templateargs);
+ Delete(parms);
+ Delete(templateargs);
+ }
+
+ Delete(pp_qprefix);
+ Delete(pp_tprefix);
+ Delete(qprefix);
+ Delete(tprefix);
+ }
+
+ Delete(pp_tsuffix);
+ Delete(pp_qt);
+ Delete(tsuffix);
+ Delete(qt);
+ }
}
}
/*
@@ -828,7 +926,6 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym
/* Rank each template parameter against the desired template parameters then build a matrix of best matches */
possiblepartials = NewList();
{
- char tmp[32];
List *partials;
partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */
@@ -852,12 +949,11 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym
if (ParmList_len(partialparms) == parms_len) {
while (p && pp) {
SwigType *t;
- sprintf(tmp, "$%d", i);
t = Getattr(p, "type");
if (!t)
t = Getattr(p, "value");
if (t) {
- EMatch match = does_parm_match(t, Getattr(pp, "type"), tmp, tscope, priorities_row + i - 1);
+ EMatch match = does_parm_match(t, Getattr(pp, "type"), tscope, priorities_row + i - 1);
if (match < (int)PartiallySpecializedMatch) {
all_parameters_match = 0;
break;
@@ -1062,7 +1158,8 @@ Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String
isclass = (Equal(Getattr(n, "templatetype"), "class"));
if (isclass) {
- Parm *tparmsfound = Getattr(n, "templateparms");
+ Node *primary = Getattr(n, "primarytemplate");
+ Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms");
int specialized = !tparmsfound; /* fully specialized (an explicit specialization) */
int variadic = ParmList_variadic_parm(tparmsfound) != 0;
if (!specialized) {
@@ -1171,15 +1268,16 @@ static int merge_parameters(ParmList *expanded_templateparms, ParmList *template
}
/* -----------------------------------------------------------------------------
- * mark_defaults()
+ * use_mark_defaults()
*
- * Mark all the template parameters that are expanded from a default value
+ * Mark and use all the template parameters that are expanded from a default value
* ----------------------------------------------------------------------------- */
-static void mark_defaults(ParmList *defaults) {
+static void use_mark_defaults(ParmList *defaults) {
Parm *tp = defaults;
while (tp) {
Setattr(tp, "default", "1");
+ Setattr(tp, "type", Getattr(tp, "value"));
tp = nextSibling(tp);
}
}
@@ -1222,12 +1320,12 @@ static void expand_defaults(ParmList *expanded_templateparms) {
* arguments filled in where necessary.
* ----------------------------------------------------------------------------- */
-ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary) {
+ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) {
ParmList *expanded_templateparms = 0;
- ParmList *templateparms = Getattr(primary, "templateparms");
if (Equal(Getattr(primary, "templatetype"), "class")) {
/* Templated class */
+ ParmList *templateparms = Getattr(primary, "templateparms");
expanded_templateparms = CopyParmList(instantiated_parms);
int variadic = merge_parameters(expanded_templateparms, templateparms);
/* Add default arguments from primary template */
@@ -1235,7 +1333,7 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *
ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parms));
if (defaults_start) {
ParmList *defaults = CopyParmList(defaults_start);
- mark_defaults(defaults);
+ use_mark_defaults(defaults);
expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
expand_defaults(expanded_templateparms);
}
@@ -1243,6 +1341,7 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *
} else {
/* Templated function */
/* TODO: Default template parameters support was only added in C++11 */
+ ParmList *templateparms = Getattr(templ, "templateparms");
expanded_templateparms = CopyParmList(instantiated_parms);
merge_parameters(expanded_templateparms, templateparms);
}