mirror of https://github.com/swig/swig
Partial template specialization fixes to support default arguments
Default argments come from the primary template's parameter list. Example: template<class Y, class T=int> struct X { void primary() {} }; // Previously the specialization below resulted in: // Error: Inconsistent argument count in template partial specialization. 1 2 template<class YY> struct X<YY*> { void special(YY*) {} }; // Both of these correctly wrap the partially specialized template %template(StringPtr) X<const char *>; %template(ShortPtr) X<short *, int>;
This commit is contained in:
parent
a55e429bf2
commit
9924c5c3e1
|
@ -7,6 +7,19 @@ 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-03-01: wsfulton
|
||||||
|
Partial template specialization fixes to support default arguments from the primary
|
||||||
|
template's parameter list.
|
||||||
|
|
||||||
|
template<class Y, class T=int> struct X { void primary() {} };
|
||||||
|
// Previously the specialization below resulted in:
|
||||||
|
// Error: Inconsistent argument count in template partial specialization. 1 2
|
||||||
|
template<class YY> struct X<YY*> { void special(YY*) {} };
|
||||||
|
|
||||||
|
// Both of these correctly wrap the partially specialized template
|
||||||
|
%template(StringPtr) X<const char *>;
|
||||||
|
%template(ShortPtr) X<short *, int>;
|
||||||
|
|
||||||
2023-02-15: wsfulton
|
2023-02-15: wsfulton
|
||||||
#1300 Further partial template specialization fixes.
|
#1300 Further partial template specialization fixes.
|
||||||
Fixes when templates are used as a template parameter in a partially specialized
|
Fixes when templates are used as a template parameter in a partially specialized
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
%module xxx
|
||||||
|
|
||||||
|
template<class Y, class T=int> struct X { void primary() {} };
|
||||||
|
template<class YY> struct X<YY*> { void special(YY*) {} };
|
||||||
|
|
||||||
|
%template(Xbad1) X<>;
|
||||||
|
%template(Xokay1) X<const char *>;
|
||||||
|
%template(Xokay2) X<const short *, int>;
|
||||||
|
%template(Xbad2) X<const char *, int, double>;
|
|
@ -0,0 +1,2 @@
|
||||||
|
cpp_template_partial_specialization_defaults.i:6: Error: Not enough template parameters specified. Minimum of 1 required.
|
||||||
|
cpp_template_partial_specialization_defaults.i:9: Error: Too many template parameters. Maximum of 2.
|
|
@ -0,0 +1,49 @@
|
||||||
|
import template_partial_specialization_more.*;
|
||||||
|
|
||||||
|
public class template_partial_specialization_more_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("template_partial_specialization_more");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
// (1)
|
||||||
|
VectInt vi = new VectInt();
|
||||||
|
int num = new FooVectIntDouble().partially_specialized(222);
|
||||||
|
new FooShortPtrDouble().pointer_specialize((short)0);
|
||||||
|
vi = new FooVectVectInt().partially_specialized(vi);
|
||||||
|
|
||||||
|
// (2)
|
||||||
|
new HeyInts().special_hey();
|
||||||
|
|
||||||
|
// (3)
|
||||||
|
new XX1().special1();
|
||||||
|
new XX2().special2();
|
||||||
|
new XX3().special3();
|
||||||
|
|
||||||
|
// (4)
|
||||||
|
new PartiallerPrimary().primary((short)0, (short)0);
|
||||||
|
new PartiallerSpecial().special(new PlainStruct(), 999, true);
|
||||||
|
|
||||||
|
// (5)
|
||||||
|
new LystDouble().primary(11.1, new AllocatorDouble());
|
||||||
|
new LystShort().primary((short)0, new AllocatorShort());
|
||||||
|
new LystPlainStructPtr().specialized1(new PlainStruct(), new AllocatorPlainStructPtr());
|
||||||
|
new LystDoublePtrPtr().specialized2(22.2, (SWIGTYPE_p_p_double)null);
|
||||||
|
new LystConstIntRef().specialized3(100);
|
||||||
|
new LystConstStringRef().specialized3("hello");
|
||||||
|
|
||||||
|
// (6)
|
||||||
|
SpecDoubleInt d = new SpecDoubleInt();
|
||||||
|
SpecStringInt i = new SpecStringInt();
|
||||||
|
d.spec_specialized(12.3);
|
||||||
|
i.spec_specialized("hi");
|
||||||
|
template_partial_specialization_more.UseSpec1(d, d);
|
||||||
|
template_partial_specialization_more.UseSpec2(i, i);
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,32 +72,70 @@ template<typename S1, typename S2> struct Partialler<S2, S1*> { void special(S1*
|
||||||
|
|
||||||
|
|
||||||
// (5) Default args used in specialization, like std::list
|
// (5) Default args used in specialization, like std::list
|
||||||
|
%include <std_string.i>
|
||||||
%inline %{
|
%inline %{
|
||||||
template <typename A> struct Allocator {};
|
template <typename A> struct Allocator {};
|
||||||
template <typename T, class Alloc = Allocator<T> > struct Lyst { void primary(T, Allocator<T>) {} };
|
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 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) {} };
|
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) {} };
|
||||||
//template <typename TTTT> struct Lyst<const TTTT&> { void specialized3(TTTT) {} };
|
|
||||||
void test_list() {
|
void test_list() {
|
||||||
int myint = 0;
|
double mydouble = 0;
|
||||||
Lyst<int> lis;
|
Lyst<double>().primary(mydouble, Allocator<double>());
|
||||||
lis.primary(myint, Allocator<int>());
|
Lyst<short, Allocator<short> >().primary(mydouble, Allocator<short>());
|
||||||
|
|
||||||
PlainStruct ps;
|
PlainStruct ps;
|
||||||
Lyst<PlainStruct *> liss;
|
int myint = 0;
|
||||||
liss.specialized1(ps, Allocator<PlainStruct *>());
|
std::string mystring = 0;
|
||||||
|
Lyst<PlainStruct *>().specialized1(ps, Allocator<PlainStruct *>());
|
||||||
double mydouble = 0;
|
Lyst<double **>().specialized2(mydouble, (double **)0);
|
||||||
Lyst<double **> lissd;
|
Lyst<const int&>().specialized3(myint);
|
||||||
lissd.specialized2(mydouble, (double **)0);
|
// Specifying the default still calls the partially specialized template
|
||||||
|
Lyst<std::string const &, Allocator<std::string const &> >().specialized3(mystring);
|
||||||
// Lyst<const int&> lissconstint;
|
|
||||||
// lissconstint.specialized3(myint);
|
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%template(AllocatorDouble) Allocator<double>;
|
||||||
|
%template(AllocatorShort) Allocator<short>;
|
||||||
|
%template(AllocatorPlainStructPtr) Allocator<PlainStruct *>;
|
||||||
|
|
||||||
%template(LystDouble) Lyst<double>;
|
%template(LystDouble) Lyst<double>;
|
||||||
//%template(LystDouble) Lyst<short, Allocator<short> >;
|
%template(LystShort) Lyst<short, Allocator<short> >;
|
||||||
%template(LystPlainStructPtr) Lyst<PlainStruct *>;
|
%template(LystPlainStructPtr) Lyst<PlainStruct *>;
|
||||||
%template(LystDoublePtrPtr) Lyst<double **>; // called specialized1 instead of specialized2
|
%template(LystDoublePtrPtr) Lyst<double **>; // called specialized1 instead of specialized2
|
||||||
|
%template(LystConstIntRef) Lyst<const int&>;
|
||||||
|
%template(LystConstStringRef) Lyst<const std::string&, Allocator<const std::string&> >;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
// Both parameters in each of the functions below are the same type
|
||||||
|
void UseLystDouble(Lyst<double> a, Lyst<double, Allocator<double> > b) {}
|
||||||
|
void UseLystShort(Lyst<short> a, Lyst<short, Allocator<short> > b) {}
|
||||||
|
void UseLystPlainStructPtr(Lyst<PlainStruct *> a, Lyst<PlainStruct *, Allocator<PlainStruct *> > b) {}
|
||||||
|
void UseLystDoublePtrPtr(Lyst<double **> a, Lyst<double **, Allocator<double **> > b) {}
|
||||||
|
void UseLystConstIntRef(Lyst<const int&> a, Lyst<const int&, Allocator<const int&> > b) {}
|
||||||
|
void UseLystConstStringRef(Lyst<const std::string&> a, Lyst<const std::string&, Allocator<const std::string&> > b) {}
|
||||||
|
%}
|
||||||
|
|
||||||
|
// (6) Default args used in specialization, more variations specifying / not specifying default
|
||||||
|
%inline %{
|
||||||
|
template<typename P, typename Q = int> struct Spec { void spec_primary(P p, Q q) {} };
|
||||||
|
template<typename PP> struct Spec<const PP&, int> { void spec_specialized(PP pp) {} };
|
||||||
|
%}
|
||||||
|
|
||||||
|
%template(SpecDoubleInt) Spec<const double&, int>;
|
||||||
|
%template(SpecStringInt) Spec<const std::string&>;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
void UseSpec1(Spec<const double&, int> x, Spec<const double&, int> y) {}
|
||||||
|
void UseSpec2(Spec<const std::string&, int> x, Spec<const std::string&, int> y) {}
|
||||||
|
void test_spec() {
|
||||||
|
double mydouble = 0.0;
|
||||||
|
Spec<const double&, int>().spec_specialized(mydouble);
|
||||||
|
Spec<const double&>().spec_specialized(mydouble);
|
||||||
|
|
||||||
|
std::string mystring;
|
||||||
|
Spec<const std::string&, int>().spec_specialized(mystring);
|
||||||
|
Spec<const std::string&>().spec_specialized(mystring);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
|
@ -69,6 +69,7 @@ extern "C" {
|
||||||
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, Node *templ);
|
extern ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parameters, Node *primary, Node *templ);
|
||||||
|
extern ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -4121,10 +4121,10 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
|
||||||
set_nodeType($$,"template");
|
set_nodeType($$,"template");
|
||||||
/* Template partial specialization */
|
/* Template partial specialization */
|
||||||
if (tempn && ($3) && ($6)) {
|
if (tempn && ($3) && ($6)) {
|
||||||
List *tlist;
|
ParmList *primary_templateparms = Getattr(tempn, "templateparms");
|
||||||
String *targs = SwigType_templateargs(tname);
|
String *targs = SwigType_templateargs(tname); /* tname contains name and specialized template parameters, for example: X<(p.T,TT)> */
|
||||||
tlist = SwigType_parmlist(targs);
|
List *tlist = SwigType_parmlist(targs);
|
||||||
/* Printf(stdout,"targs = '%s' %s\n", targs, tlist); */
|
int specialization_parms_len = Len(tlist);
|
||||||
if (!Getattr($$,"sym:weak")) {
|
if (!Getattr($$,"sym:weak")) {
|
||||||
Setattr($$,"sym:typename","1");
|
Setattr($$,"sym:typename","1");
|
||||||
}
|
}
|
||||||
|
@ -4133,13 +4133,15 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
|
||||||
Delattr($$, "specialization");
|
Delattr($$, "specialization");
|
||||||
Setattr($$, "partialspecialization", "1");
|
Setattr($$, "partialspecialization", "1");
|
||||||
|
|
||||||
if (Len(tlist) != ParmList_len(Getattr(tempn,"templateparms"))) {
|
if (specialization_parms_len > ParmList_len(primary_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($$), "Template partial specialization has more arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
|
||||||
|
|
||||||
|
} else if (specialization_parms_len < ParmList_numrequired(primary_templateparms)) {
|
||||||
|
Swig_error(Getfile($$), Getline($$), "Template partial specialization has fewer arguments than primary template %d %d.\n", specialization_parms_len, ParmList_len(primary_templateparms));
|
||||||
} else {
|
} else {
|
||||||
/* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
|
/* Create a specialized name with template parameters replaced with $ variables, such as, X<(T1,p.T2) => X<($1,p.$2)> */
|
||||||
Parm *p = $3;
|
Parm *p = $3;
|
||||||
String *fname = NewString(Getattr($$,"name"));
|
String *fname = NewString(tname);
|
||||||
String *ffname = 0;
|
String *ffname = 0;
|
||||||
ParmList *partialparms = 0;
|
ParmList *partialparms = 0;
|
||||||
|
|
||||||
|
@ -4183,6 +4185,27 @@ cpp_template_decl : TEMPLATE LESSTHAN template_parms GREATERTHAN {
|
||||||
Delete(tparms);
|
Delete(tparms);
|
||||||
Append(ffname,")>");
|
Append(ffname,")>");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
/* Replace each primary template parameter's name and value with $ variables, such as, class Y,class T=Y => class $1,class $2=$1 */
|
||||||
|
ParmList *primary_templateparms_copy = CopyParmList(primary_templateparms);
|
||||||
|
p = primary_templateparms_copy;
|
||||||
|
i = 0;
|
||||||
|
while (p) {
|
||||||
|
String *name = Getattr(p, "name");
|
||||||
|
Parm *pp = nextSibling(p);
|
||||||
|
++i;
|
||||||
|
sprintf(tmp, "$%d", i);
|
||||||
|
while (pp) {
|
||||||
|
Replaceid(Getattr(pp, "value"), name, tmp);
|
||||||
|
pp = nextSibling(pp);
|
||||||
|
}
|
||||||
|
Setattr(p, "name", NewString(tmp));
|
||||||
|
p = nextSibling(p);
|
||||||
|
}
|
||||||
|
/* Modify partialparms by adding in missing default values ($ variables) from primary template parameters */
|
||||||
|
partialparms = Swig_cparse_template_partialargs_expand(partialparms, tempn, primary_templateparms_copy);
|
||||||
|
Delete(primary_templateparms_copy);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Node *new_partial = NewHash();
|
Node *new_partial = NewHash();
|
||||||
String *partials = Getattr(tempn,"partials");
|
String *partials = Getattr(tempn,"partials");
|
||||||
|
|
|
@ -498,7 +498,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
||||||
p = nextSibling(p);
|
p = nextSibling(p);
|
||||||
tp = nextSibling(tp);
|
tp = nextSibling(tp);
|
||||||
}
|
}
|
||||||
assert(ParmList_len(ptargs) == ParmList_len(tparms));
|
|
||||||
Delete(ptargs);
|
Delete(ptargs);
|
||||||
} else {
|
} else {
|
||||||
Setattr(n, "templateparmsraw", Getattr(n, "templateparms"));
|
Setattr(n, "templateparmsraw", Getattr(n, "templateparms"));
|
||||||
|
@ -835,7 +834,7 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym
|
||||||
targs = Getattr(templ, "templateparms");
|
targs = Getattr(templ, "templateparms");
|
||||||
expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope);
|
expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope);
|
||||||
|
|
||||||
/* reduce the typedef */
|
/* Qualify template parameters */
|
||||||
p = expandedparms;
|
p = expandedparms;
|
||||||
while (p) {
|
while (p) {
|
||||||
SwigType *ty = Getattr(p, "type");
|
SwigType *ty = Getattr(p, "type");
|
||||||
|
@ -934,14 +933,13 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym
|
||||||
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 */
|
||||||
if (partials) {
|
if (partials) {
|
||||||
Iterator pi;
|
Iterator pi;
|
||||||
int parms_len = ParmList_len(parms);
|
int parms_len = ParmList_len(parms); /* max parameters including defaulted parameters from primary template (ie max parameters) */
|
||||||
int *priorities_row;
|
int *priorities_row;
|
||||||
max_possible_partials = Len(partials);
|
max_possible_partials = Len(partials);
|
||||||
priorities_matrix = (int *)Malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */
|
priorities_matrix = (int *)Malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */
|
||||||
priorities_row = priorities_matrix;
|
priorities_row = priorities_matrix;
|
||||||
for (pi = First(partials); pi.item; pi = Next(pi)) {
|
for (pi = First(partials); pi.item; pi = Next(pi)) {
|
||||||
Parm *p = parms;
|
Parm *p = parms;
|
||||||
int all_parameters_match = 1;
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
Parm *partialparms = Getattr(pi.item, "partialparms");
|
Parm *partialparms = Getattr(pi.item, "partialparms");
|
||||||
Parm *pp = partialparms;
|
Parm *pp = partialparms;
|
||||||
|
@ -950,6 +948,7 @@ static Node *template_locate(String *name, Parm *instantiated_parms, String *sym
|
||||||
Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname);
|
Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname);
|
||||||
}
|
}
|
||||||
if (ParmList_len(partialparms) == parms_len) {
|
if (ParmList_len(partialparms) == parms_len) {
|
||||||
|
int all_parameters_match = 1;
|
||||||
while (p && pp) {
|
while (p && pp) {
|
||||||
SwigType *t;
|
SwigType *t;
|
||||||
t = Getattr(p, "type");
|
t = Getattr(p, "type");
|
||||||
|
@ -1165,15 +1164,18 @@ Node *Swig_cparse_template_locate(String *name, Parm *instantiated_parms, String
|
||||||
Parm *tparmsfound = Getattr(primary ? primary : n, "templateparms");
|
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;
|
||||||
|
match = n;
|
||||||
if (!specialized) {
|
if (!specialized) {
|
||||||
if (!variadic && (ParmList_len(instantiated_parms) > ParmList_len(tparmsfound))) {
|
if (!variadic && (ParmList_len(instantiated_parms) > ParmList_len(tparmsfound))) {
|
||||||
Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparmsfound));
|
Swig_error(cparse_file, cparse_line, "Too many template parameters. Maximum of %d.\n", ParmList_len(tparmsfound));
|
||||||
|
match = 0;
|
||||||
} else if (ParmList_len(instantiated_parms) < ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) { /* Variadic parameter is optional */
|
} else if (ParmList_len(instantiated_parms) < ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) { /* Variadic parameter is optional */
|
||||||
Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. %d required.\n", (ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) );
|
Swig_error(cparse_file, cparse_line, "Not enough template parameters specified. Minimum of %d required.\n", (ParmList_numrequired(tparmsfound) - (variadic ? 1 : 0)) );
|
||||||
|
match = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SetFlag(n, "instantiate");
|
if (match)
|
||||||
match = n;
|
SetFlag(n, "instantiate");
|
||||||
} else {
|
} else {
|
||||||
Node *firstn = 0;
|
Node *firstn = 0;
|
||||||
/* If not a templated class we must have a templated function.
|
/* If not a templated class we must have a templated function.
|
||||||
|
@ -1285,6 +1287,22 @@ static void use_mark_defaults(ParmList *defaults) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* use_mark_specialized_defaults()
|
||||||
|
*
|
||||||
|
* Modify extra defaulted parameters ready for adding to specialized template parameters list
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static void use_mark_specialized_defaults(ParmList *defaults) {
|
||||||
|
Parm *tp = defaults;
|
||||||
|
while (tp) {
|
||||||
|
Setattr(tp, "default", "1");
|
||||||
|
Setattr(tp, "type", Getattr(tp, "value"));
|
||||||
|
Delattr(tp, "name");
|
||||||
|
tp = nextSibling(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* expand_defaults()
|
* expand_defaults()
|
||||||
*
|
*
|
||||||
|
@ -1324,12 +1342,11 @@ static void expand_defaults(ParmList *expanded_templateparms) {
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) {
|
ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *primary, Node *templ) {
|
||||||
ParmList *expanded_templateparms = 0;
|
ParmList *expanded_templateparms = CopyParmList(instantiated_parms);
|
||||||
|
|
||||||
if (Equal(Getattr(primary, "templatetype"), "class")) {
|
if (Equal(Getattr(primary, "templatetype"), "class")) {
|
||||||
/* Templated class */
|
/* Templated class */
|
||||||
ParmList *templateparms = Getattr(primary, "templateparms");
|
ParmList *templateparms = Getattr(primary, "templateparms");
|
||||||
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 */
|
||||||
if (!variadic) {
|
if (!variadic) {
|
||||||
|
@ -1345,9 +1362,43 @@ ParmList *Swig_cparse_template_parms_expand(ParmList *instantiated_parms, Node *
|
||||||
/* 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");
|
ParmList *templateparms = Getattr(templ, "templateparms");
|
||||||
expanded_templateparms = CopyParmList(instantiated_parms);
|
|
||||||
merge_parameters(expanded_templateparms, templateparms);
|
merge_parameters(expanded_templateparms, templateparms);
|
||||||
}
|
}
|
||||||
|
|
||||||
return expanded_templateparms;
|
return expanded_templateparms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------------------------
|
||||||
|
* Swig_cparse_template_partialargs_expand()
|
||||||
|
*
|
||||||
|
* partially_specialized_parms: partially specialized template parameters
|
||||||
|
* primary: primary template node
|
||||||
|
* templateparms: primary template parameters (providing the defaults)
|
||||||
|
*
|
||||||
|
* Expand the partially_specialized_parms and return a parameter list with default
|
||||||
|
* arguments filled in where necessary.
|
||||||
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ParmList *Swig_cparse_template_partialargs_expand(ParmList *partially_specialized_parms, Node *primary, ParmList *templateparms) {
|
||||||
|
ParmList *expanded_templateparms = CopyParmList(partially_specialized_parms);
|
||||||
|
|
||||||
|
if (Equal(Getattr(primary, "templatetype"), "class")) {
|
||||||
|
/* Templated class */
|
||||||
|
int variadic = ParmList_variadic_parm(templateparms) ? 1 : 0;
|
||||||
|
/* Add default arguments from primary template */
|
||||||
|
if (!variadic) {
|
||||||
|
ParmList *defaults_start = ParmList_nth_parm(templateparms, ParmList_len(partially_specialized_parms));
|
||||||
|
if (defaults_start) {
|
||||||
|
ParmList *defaults = CopyParmList(defaults_start);
|
||||||
|
use_mark_specialized_defaults(defaults);
|
||||||
|
expanded_templateparms = ParmList_join(expanded_templateparms, defaults);
|
||||||
|
expand_defaults(expanded_templateparms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Templated function */
|
||||||
|
/* TODO: Default template parameters support was only added in C++11 */
|
||||||
|
}
|
||||||
|
|
||||||
|
return expanded_templateparms;
|
||||||
|
}
|
||||||
|
|
|
@ -190,7 +190,8 @@ Parm *ParmList_variadic_parm(ParmList *p) {
|
||||||
/* -----------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------
|
||||||
* ParmList_numrequired()
|
* ParmList_numrequired()
|
||||||
*
|
*
|
||||||
* Return number of required arguments
|
* Return number of required arguments - the number of arguments excluding
|
||||||
|
* default arguments
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
int ParmList_numrequired(ParmList *p) {
|
int ParmList_numrequired(ParmList *p) {
|
||||||
|
|
Loading…
Reference in New Issue