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.
This commit is contained in:
parent
bd2de6fc06
commit
817c700ced
6 changed files with 309 additions and 169 deletions
|
|
@ -7,6 +7,24 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
||||||
Version 4.2.0 (in progress)
|
Version 4.2.0 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2023-02-15: wsfulton
|
||||||
|
#1300 Further partial template specialization fixes.
|
||||||
|
Fixes when templates are used as a template parameter in a partially specialized
|
||||||
|
instantiation such as:
|
||||||
|
|
||||||
|
template<typename V> struct Vect {};
|
||||||
|
template<class T, typename TT> class Foo { ... };
|
||||||
|
template<class TS, typename TTS> class Foo<Vect<TS>, TTS> { ... };
|
||||||
|
%template(VectInt) Vect<int>;
|
||||||
|
%template(FooVectIntDouble) Foo<Vect<int>, double>; // was previously attempting to use primary template
|
||||||
|
|
||||||
|
Also fixes partial specialization where the same template parameter name is used twice,
|
||||||
|
for example:
|
||||||
|
|
||||||
|
template<typename X, typename Y> struct H { ... };
|
||||||
|
template<typename T> struct H<T, T> { ... };
|
||||||
|
%template(HInts) H<int, int>; // was previously attempting to use primary template
|
||||||
|
|
||||||
2023-01-27: jschueller
|
2023-01-27: jschueller
|
||||||
#2492 [python] Fix unused parameter warnings for self parameter in
|
#2492 [python] Fix unused parameter warnings for self parameter in
|
||||||
generated C/C++ wrapper code.
|
generated C/C++ wrapper code.
|
||||||
|
|
|
||||||
|
|
@ -487,6 +487,7 @@ CPP_TEST_CASES += \
|
||||||
template_parameters_global_scope \
|
template_parameters_global_scope \
|
||||||
template_partial_arg \
|
template_partial_arg \
|
||||||
template_partial_specialization \
|
template_partial_specialization \
|
||||||
|
template_partial_specialization_more \
|
||||||
template_partial_specialization_typedef \
|
template_partial_specialization_typedef \
|
||||||
template_qualifier \
|
template_qualifier \
|
||||||
template_ref_type \
|
template_ref_type \
|
||||||
|
|
|
||||||
103
Examples/test-suite/template_partial_specialization_more.i
Normal file
103
Examples/test-suite/template_partial_specialization_more.i
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
%module template_partial_specialization_more
|
||||||
|
|
||||||
|
|
||||||
|
// (1) Based on https://stackoverflow.com/questions/9757642/wrapping-specialised-c-template-class-with-swig
|
||||||
|
%inline %{
|
||||||
|
template<typename V> struct Vect {};
|
||||||
|
template<class T, typename TT>
|
||||||
|
class Foo {
|
||||||
|
public:
|
||||||
|
Foo() {}
|
||||||
|
virtual ~Foo() {}
|
||||||
|
T primary() const { return T(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class TS, typename TTS>
|
||||||
|
class Foo<Vect<TS>, TTS> {
|
||||||
|
public:
|
||||||
|
Foo() {}
|
||||||
|
virtual ~Foo() {}
|
||||||
|
TS partially_specialized(TS parmin) const { return parmin; }
|
||||||
|
};
|
||||||
|
template<>
|
||||||
|
class Foo<Vect<double>, double> {
|
||||||
|
public:
|
||||||
|
Foo() {}
|
||||||
|
virtual ~Foo() {}
|
||||||
|
double value_fully_specialized(double d) const { return d; }
|
||||||
|
};
|
||||||
|
template<class T, typename TT>
|
||||||
|
class Foo<T*, TT> {
|
||||||
|
public:
|
||||||
|
Foo() {}
|
||||||
|
virtual ~Foo() {}
|
||||||
|
int pointer_specialize(T myT) const { return 0; }
|
||||||
|
};
|
||||||
|
%}
|
||||||
|
%template(VectInt) Vect<int>;
|
||||||
|
%template(FooVectIntDouble) Foo<Vect<int>, double>; // was failing
|
||||||
|
%template(FooShortPtrDouble) Foo<short*, double>;
|
||||||
|
%template(FooVectVectInt) Foo<Vect<Vect<int>>, int>; // was failing
|
||||||
|
|
||||||
|
|
||||||
|
// (2) Same types in both args
|
||||||
|
%inline %{
|
||||||
|
template<typename X, typename Y> struct Hey { void primary() {} };
|
||||||
|
template<typename T> struct Hey<T, T> { void special_hey() {} };
|
||||||
|
%}
|
||||||
|
%template(HeyInts) Hey<int, int>; // was failing, was calling primary
|
||||||
|
|
||||||
|
|
||||||
|
// (3) Partial specialization using one template parameter instead of two
|
||||||
|
%inline %{
|
||||||
|
struct PlainStruct {};
|
||||||
|
template <typename T, typename U> struct XX { void primary() {} };
|
||||||
|
template <typename T> struct XX<T, T &> { void special1() {} }; // r.$1
|
||||||
|
template <typename T> struct XX<T, T const&> { void special2() {} }; // r.q(const).$1
|
||||||
|
template <typename T> struct XX<T, T *const&> { void special3() {} }; // r.q(const).p.$1
|
||||||
|
%}
|
||||||
|
%template(XX1) XX<int, int&>; // was failing, was calling primary
|
||||||
|
%template(XX2) XX<int, int const&>;
|
||||||
|
%template(XX3) XX<PlainStruct, PlainStruct *const&>;
|
||||||
|
|
||||||
|
|
||||||
|
// (4) Switching parameters around
|
||||||
|
%inline %{
|
||||||
|
#include <iostream>
|
||||||
|
template<typename P1 = int, typename P2 = double> struct Partialler { void primary(P1, P2) {}; };
|
||||||
|
template<typename S1, typename S2> struct Partialler<S2, S1*> { void special(S1*, S2, bool) {}; };
|
||||||
|
%}
|
||||||
|
%template(PartiallerPrimary) Partialler<short, short>;
|
||||||
|
%template(PartiallerSpecial) Partialler<int, PlainStruct*>;
|
||||||
|
|
||||||
|
|
||||||
|
// (5) Default args used in specialization, like std::list
|
||||||
|
%inline %{
|
||||||
|
template <typename A> struct Allocator {};
|
||||||
|
template <typename T, class Alloc = Allocator<T>> struct Lyst { void primary(T, Allocator<T>) {} };
|
||||||
|
template <typename TT, class XXAlloc> struct Lyst<TT*, XXAlloc> { void specialized1(TT, XXAlloc) {} };
|
||||||
|
template <typename TTT, class YY> struct Lyst<TTT**, Allocator<YY>> { void specialized2(TTT, YY) {} };
|
||||||
|
// TODO Error: Inconsistent argument count in template partial specialization. 1 2
|
||||||
|
//template <typename TTTT> struct Lyst<const TTTT&> { void specialized3(TTTT) {} };
|
||||||
|
void test_list() {
|
||||||
|
int myint = 0;
|
||||||
|
Lyst<int> lis;
|
||||||
|
lis.primary(myint, Allocator<int>());
|
||||||
|
|
||||||
|
PlainStruct ps;
|
||||||
|
Lyst<PlainStruct *> liss;
|
||||||
|
liss.specialized1(ps, Allocator<PlainStruct *>());
|
||||||
|
|
||||||
|
double mydouble = 0;
|
||||||
|
Lyst<double **> lissd;
|
||||||
|
lissd.specialized2(mydouble, (double **)nullptr);
|
||||||
|
|
||||||
|
// Lyst<const int&> lissconstint;
|
||||||
|
// lissconstint.specialized3(myint);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template(LystDouble) Lyst<double>;
|
||||||
|
//%template(LystDouble) Lyst<short, Allocator<short>>;
|
||||||
|
%template(LystPlainStructPtr) Lyst<PlainStruct *>;
|
||||||
|
%template(LystDoublePtrPtr) Lyst<double **>; // called specialized1 instead of specialized2
|
||||||
|
|
@ -68,7 +68,7 @@ extern "C" {
|
||||||
extern int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope);
|
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 Node *Swig_cparse_template_locate(String *name, ParmList *tparms, String *symname, Symtab *tscope);
|
||||||
extern void Swig_cparse_debug_templates(int);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2883,7 +2883,7 @@ template_directive: SWIGTEMPLATE LPAREN idstringopt RPAREN idcolonnt LESSTHAN va
|
||||||
Node *primary_template = Swig_symbol_clookup(tname, 0);
|
Node *primary_template = Swig_symbol_clookup(tname, 0);
|
||||||
|
|
||||||
/* Expand the template */
|
/* 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);
|
templnode = copy_node(nn);
|
||||||
update_nested_classes(templnode); /* update classes nested within template */
|
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")) {
|
if (!Getattr($$,"sym:weak")) {
|
||||||
Setattr($$,"sym:typename","1");
|
Setattr($$,"sym:typename","1");
|
||||||
}
|
}
|
||||||
|
Setattr($$, "primarytemplate", tempn);
|
||||||
|
Setattr($$, "templateparms", $3);
|
||||||
|
Delattr($$, "specialization");
|
||||||
|
Setattr($$, "partialspecialization", "1");
|
||||||
|
|
||||||
if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) {
|
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")));
|
Swig_error(Getfile($$),Getline($$),"Inconsistent argument count in template partial specialization. %d %d\n", Len(tlist), ParmList_len(Getattr(tempn,"templateparms")));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
/* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
|
||||||
/* 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 */
|
|
||||||
{
|
|
||||||
Parm *p = $3;
|
Parm *p = $3;
|
||||||
String *fname = NewString(Getattr($$,"name"));
|
String *fname = NewString(Getattr($$,"name"));
|
||||||
String *ffname = 0;
|
String *ffname = 0;
|
||||||
ParmList *partialparms = 0;
|
ParmList *partialparms = 0;
|
||||||
|
|
||||||
char tmp[32];
|
char tmp[32];
|
||||||
int i, ilen;
|
int i = 0;
|
||||||
while (p) {
|
while (p) {
|
||||||
String *n = Getattr(p,"name");
|
String *name = Getattr(p,"name");
|
||||||
if (!n) {
|
++i;
|
||||||
|
if (!name) {
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ilen = Len(tlist);
|
sprintf(tmp, "$%d", i);
|
||||||
for (i = 0; i < ilen; i++) {
|
Replaceid(fname, name, tmp);
|
||||||
if (Strstr(Getitem(tlist,i),n)) {
|
|
||||||
sprintf(tmp,"$%d",i+1);
|
|
||||||
Replaceid(fname,n,tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
}
|
}
|
||||||
/* Patch argument names with typedef */
|
/* Patch argument names with typedef */
|
||||||
|
|
@ -4279,7 +4199,6 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
|
||||||
Setattr($$,"partialargs",ffname);
|
Setattr($$,"partialargs",ffname);
|
||||||
Swig_symbol_cadd(ffname,$$);
|
Swig_symbol_cadd(ffname,$$);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Delete(tlist);
|
Delete(tlist);
|
||||||
Delete(targs);
|
Delete(targs);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "swig.h"
|
#include "swig.h"
|
||||||
#include "cparse.h"
|
#include "cparse.h"
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
static int template_debug = 0;
|
static int template_debug = 0;
|
||||||
|
|
||||||
|
|
@ -396,25 +397,43 @@ static void cparse_postprocess_expanded_template(Node *n) {
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* partial_arg()
|
* 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) {
|
static Parm *partial_arg(const SwigType *type, const SwigType *partialtype) {
|
||||||
char *c;
|
SwigType *parmtype;
|
||||||
char *cp = Char(p);
|
String *parmname = 0;
|
||||||
String *prefix;
|
const char *cp = Char(partialtype);
|
||||||
String *newarg;
|
const char *c = strchr(cp, '$');
|
||||||
|
|
||||||
/* Find the prefix on the partial argument */
|
if (c) {
|
||||||
|
int suffix_length;
|
||||||
c = strchr(cp, '$');
|
int prefix_length = c - cp;
|
||||||
if (!c) {
|
int type_length = Len(type);
|
||||||
return Copy(s);
|
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));
|
return NewParmWithoutFileLineInfo(parmtype, parmname);
|
||||||
newarg = Copy(s);
|
|
||||||
Replace(newarg, prefix, "", DOH_REPLACE_FIRST);
|
|
||||||
Delete(prefix);
|
|
||||||
return newarg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
|
|
@ -429,6 +448,8 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
||||||
String *tbase;
|
String *tbase;
|
||||||
Parm *unexpanded_variadic_parm = 0;
|
Parm *unexpanded_variadic_parm = 0;
|
||||||
ParmList *expanded_variadic_parms = 0;
|
ParmList *expanded_variadic_parms = 0;
|
||||||
|
ParmList *templateparms = Getattr(n, "templateparms");
|
||||||
|
ParmList *templateparmsraw = 0;
|
||||||
patchlist = NewList(); /* List of String * ("name" and "value" attributes) */
|
patchlist = NewList(); /* List of String * ("name" and "value" attributes) */
|
||||||
cpatchlist = NewList(); /* List of String * (code) */
|
cpatchlist = NewList(); /* List of String * (code) */
|
||||||
typelist = NewList(); /* List of SwigType * types */
|
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"));
|
tname = Copy(Getattr(n, "name"));
|
||||||
tbase = Swig_scopename_last(tname);
|
tbase = Swig_scopename_last(tname);
|
||||||
|
|
||||||
/* Look for partial specialization matching */
|
|
||||||
if (Getattr(n, "partialargs")) {
|
if (Getattr(n, "partialargs")) {
|
||||||
|
/* Partial specialization */
|
||||||
Parm *p, *tp;
|
Parm *p, *tp;
|
||||||
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
|
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
|
||||||
p = ptargs;
|
p = ptargs;
|
||||||
tp = tparms;
|
tp = tparms;
|
||||||
|
/* Adjust templateparms so that the type is expanded, eg typename => int */
|
||||||
while (p && tp) {
|
while (p && tp) {
|
||||||
SwigType *ptype;
|
SwigType *ptype;
|
||||||
SwigType *tptype;
|
SwigType *tptype;
|
||||||
|
|
@ -453,9 +475,20 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
||||||
tptype = Getattr(tp, "type");
|
tptype = Getattr(tp, "type");
|
||||||
if (ptype && tptype) {
|
if (ptype && tptype) {
|
||||||
SwigType *ty = Swig_symbol_typedef_reduce(tptype, tscope);
|
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); */
|
/* 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(partial_type);
|
||||||
Delete(ty);
|
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));
|
assert(ParmList_len(ptargs) == ParmList_len(tparms));
|
||||||
Delete(ptargs);
|
Delete(ptargs);
|
||||||
|
} else {
|
||||||
|
Setattr(n, "templateparmsraw", Getattr(n, "templateparms"));
|
||||||
|
templateparms = CopyParmList(tparms);
|
||||||
|
Setattr(n, "templateparms", templateparms);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* TODO: variadic parms for partially specialized templates */
|
||||||
Parm *p = tparms;
|
templateparmsraw = Getattr(n, "templateparmsraw");
|
||||||
while (p) {
|
unexpanded_variadic_parm = ParmList_variadic_parm(templateparmsraw);
|
||||||
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);
|
|
||||||
if (unexpanded_variadic_parm)
|
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,"targs = '%s'\n", templateargs);
|
||||||
Printf(stdout,"rname = '%s'\n", rname);
|
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 */
|
/* Patch all of the types */
|
||||||
{
|
{
|
||||||
Parm *tp = Getattr(n, "templateparms");
|
Parm *tp = Getattr(n, "templateparms");
|
||||||
Parm *p = tparms;
|
|
||||||
/* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
|
/* Printf(stdout,"%s\n", ParmList_str_defaultargs(tp)); */
|
||||||
|
|
||||||
if (p && tp) {
|
if (tp) {
|
||||||
Symtab *tsdecl = Getattr(n, "sym:symtab");
|
Symtab *tsdecl = Getattr(n, "sym:symtab");
|
||||||
String *tsname = Getattr(n, "sym:name");
|
String *tsname = Getattr(n, "sym:name");
|
||||||
while (p && tp) {
|
while (tp) {
|
||||||
String *name, *value, *valuestr, *tmp, *tmpr;
|
String *name, *value, *valuestr, *tmp, *tmpr;
|
||||||
int sz, i;
|
int sz, i;
|
||||||
String *dvalue = 0;
|
String *dvalue = 0;
|
||||||
String *qvalue = 0;
|
String *qvalue = 0;
|
||||||
|
|
||||||
name = Getattr(tp, "name");
|
name = Getattr(tp, "name");
|
||||||
value = Getattr(p, "value");
|
value = Getattr(tp, "value");
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
if (!value)
|
if (!value)
|
||||||
value = Getattr(p, "type");
|
value = Getattr(tp, "type");
|
||||||
qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
|
qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
|
||||||
dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
|
dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
|
||||||
if (SwigType_istemplate(dvalue)) {
|
if (SwigType_istemplate(dvalue)) {
|
||||||
|
|
@ -524,17 +553,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
||||||
|
|
||||||
assert(dvalue);
|
assert(dvalue);
|
||||||
valuestr = SwigType_str(dvalue, 0);
|
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);
|
sz = Len(patchlist);
|
||||||
for (i = 0; i < sz; i++) {
|
for (i = 0; i < sz; i++) {
|
||||||
String *s = Getitem(patchlist, 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(dvalue);
|
||||||
Delete(qvalue);
|
Delete(qvalue);
|
||||||
}
|
}
|
||||||
p = nextSibling(p);
|
|
||||||
tp = nextSibling(tp);
|
tp = nextSibling(tp);
|
||||||
if (!p)
|
|
||||||
p = tp;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* No template parameters at all. This could be a specialization */
|
/* No template parameters at all. This could be a specialization */
|
||||||
|
|
@ -625,26 +640,47 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
||||||
|
|
||||||
typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch;
|
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()
|
* 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'.
|
* template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'.
|
||||||
*
|
*
|
||||||
* type - template parameter type to match against
|
* 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_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
|
* 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.
|
* (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 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 *ty = Swig_symbol_typedef_reduce(type, tscope);
|
||||||
SwigType *pp_prefix = SwigType_prefix(partial_parm_type);
|
SwigType *pp_prefix = SwigType_prefix(partial_parm_type);
|
||||||
int pp_len = Len(pp_prefix);
|
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;
|
*specialization_priority = -1;
|
||||||
|
|
||||||
if (Equal(ty, partial_parm_type)) {
|
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) {
|
} else if (match == PartiallySpecializedNoMatch) {
|
||||||
if ((pp_len > 0 && Strncmp(ty, pp_prefix, pp_len) == 0)) {
|
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:
|
all of the following could match the type in the %template:
|
||||||
template <typename T> struct XX {};
|
template <typename T> struct XX {};
|
||||||
template <typename T> struct XX<T &> {}; // r.$1
|
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).$1
|
||||||
template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
|
template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
|
||||||
%template(XXX) XX<int *const&>; // r.q(const).p.int
|
%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."
|
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;
|
match = PartiallySpecializedMatch;
|
||||||
*specialization_priority = pp_len;
|
*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
|
Type without a prefix match, as in $1 for int
|
||||||
template <typename T, typename U> struct XX {};
|
template <typename T, typename U> struct XX {};
|
||||||
template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2
|
template <typename T, typename U> struct XX<T, U &> {}; // $1,r.$2
|
||||||
%template(XXX) XX<int, double&>; // int,r.double
|
%template(XXX) XX<int, double&>; // int,r.double
|
||||||
*/
|
*/
|
||||||
match = PartiallySpecializedMatch;
|
match = PartiallySpecializedMatch;
|
||||||
*specialization_priority = pp_len;
|
*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 */
|
/* Rank each template parameter against the desired template parameters then build a matrix of best matches */
|
||||||
possiblepartials = NewList();
|
possiblepartials = NewList();
|
||||||
{
|
{
|
||||||
char tmp[32];
|
|
||||||
List *partials;
|
List *partials;
|
||||||
|
|
||||||
partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */
|
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) {
|
if (ParmList_len(partialparms) == parms_len) {
|
||||||
while (p && pp) {
|
while (p && pp) {
|
||||||
SwigType *t;
|
SwigType *t;
|
||||||
sprintf(tmp, "$%d", i);
|
|
||||||
t = Getattr(p, "type");
|
t = Getattr(p, "type");
|
||||||
if (!t)
|
if (!t)
|
||||||
t = Getattr(p, "value");
|
t = Getattr(p, "value");
|
||||||
if (t) {
|
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) {
|
if (match < (int)PartiallySpecializedMatch) {
|
||||||
all_parameters_match = 0;
|
all_parameters_match = 0;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1062,7 +1158,8 @@ Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String
|
||||||
isclass = (Equal(Getattr(n, "templatetype"), "class"));
|
isclass = (Equal(Getattr(n, "templatetype"), "class"));
|
||||||
|
|
||||||
if (isclass) {
|
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 specialized = !tparmsfound; /* fully specialized (an explicit specialization) */
|
||||||
int variadic = ParmList_variadic_parm(tparmsfound) != 0;
|
int variadic = ParmList_variadic_parm(tparmsfound) != 0;
|
||||||
if (!specialized) {
|
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;
|
Parm *tp = defaults;
|
||||||
while (tp) {
|
while (tp) {
|
||||||
Setattr(tp, "default", "1");
|
Setattr(tp, "default", "1");
|
||||||
|
Setattr(tp, "type", Getattr(tp, "value"));
|
||||||
tp = nextSibling(tp);
|
tp = nextSibling(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1222,12 +1320,12 @@ static void expand_defaults(ParmList *expanded_templateparms) {
|
||||||
* arguments filled in where necessary.
|
* 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 *expanded_templateparms = 0;
|
||||||
ParmList *templateparms = Getattr(primary, "templateparms");
|
|
||||||
|
|
||||||
if (Equal(Getattr(primary, "templatetype"), "class")) {
|
if (Equal(Getattr(primary, "templatetype"), "class")) {
|
||||||
/* Templated class */
|
/* Templated class */
|
||||||
|
ParmList *templateparms = Getattr(primary, "templateparms");
|
||||||
expanded_templateparms = CopyParmList(instantiated_parms);
|
expanded_templateparms = CopyParmList(instantiated_parms);
|
||||||
int variadic = merge_parameters(expanded_templateparms, templateparms);
|
int variadic = merge_parameters(expanded_templateparms, templateparms);
|
||||||
/* Add default arguments from primary template */
|
/* 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));
|
ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(instantiated_parms));
|
||||||
if (defaults_start) {
|
if (defaults_start) {
|
||||||
ParmList *defaults = CopyParmList(defaults_start);
|
ParmList *defaults = CopyParmList(defaults_start);
|
||||||
mark_defaults(defaults);
|
use_mark_defaults(defaults);
|
||||||
expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
|
expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
|
||||||
expand_defaults(expanded_templateparms);
|
expand_defaults(expanded_templateparms);
|
||||||
}
|
}
|
||||||
|
|
@ -1243,6 +1341,7 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *
|
||||||
} else {
|
} else {
|
||||||
/* Templated function */
|
/* Templated function */
|
||||||
/* TODO: Default template parameters support was only added in C++11 */
|
/* TODO: Default template parameters support was only added in C++11 */
|
||||||
|
ParmList *templateparms = Getattr(templ, "templateparms");
|
||||||
expanded_templateparms = CopyParmList(instantiated_parms);
|
expanded_templateparms = CopyParmList(instantiated_parms);
|
||||||
merge_parameters(expanded_templateparms, templateparms);
|
merge_parameters(expanded_templateparms, templateparms);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue