More refactoring for internal destructor and constructor names

Further removal of template parameters from the "name" attribute for
constructors and destructors.

Add test case for templated constructor instantiations - based on the
Python and Octave only li_std_pair_extra.i test which caused problems
making this change.
This commit is contained in:
William S Fulton 2023-07-22 18:21:32 +01:00
parent 525426911c
commit eb18619178
5 changed files with 88 additions and 37 deletions

View File

@ -21,6 +21,16 @@ public class template_templated_constructors_runme {
TClass2Int tc2a = new TClass2Int(); TClass2Int tc2a = new TClass2Int();
TClass2Int tc2b = new TClass2Int(123.4); TClass2Int tc2b = new TClass2Int(123.4);
DoublePair double_pair = new DoublePair(1.1, 2.2);
ShortPair short_pair = new ShortPair((short)0, (short)1);
StringPair string_pair = new StringPair("10", "11");
IntPair ip1 = new IntPair();
IntPair ip2 = new IntPair(20, 21);
IntPair ip3 = new IntPair(ip1);
IntPair ip4 = new IntPair(short_pair);
// These next two use IntPair constructors, unlike Python which requires factory function calls
IntPair ip5 = new IntPair(double_pair);
IntPair ip6 = new IntPair(string_pair);
} }
} }

View File

@ -0,0 +1,20 @@
from template_templated_constructors import *
t1 = TConstructor1(123)
t2a = TConstructor2()
t2b = TConstructor2(123)
tc1 = TClass1Int(123.4)
tc2a = TClass2Int()
tc2b = TClass2Int(123.4)
double_pair = DoublePair(1.1, 2.2)
short_pair = ShortPair(0, 1)
string_pair = StringPair("10", "11")
ip1 = IntPair()
ip2 = IntPair(20, 21)
ip3 = IntPair(ip1)
ip4 = IntPair(short_pair)
# These next two create an IntPair from factory function calls in Python, unlike Java which calls the IntPair constructor
ip5 = Pair(double_pair)
ip6 = MakeStringPair(string_pair)

View File

@ -59,3 +59,37 @@ public:
%extend ConstructSpace::TClass2<int> { %extend ConstructSpace::TClass2<int> {
%template(TClass2Int) TClass2<double>; %template(TClass2Int) TClass2<double>;
} }
%inline %{
// Simple version of std::pair
namespace Standard {
template <class T, class U > struct Pair {
typedef T first_type;
typedef U second_type;
Pair() {}
Pair(const T& first, const U& second) {}
Pair(const Pair& other) {}
template <class U1, class U2> Pair(const Pair< U1, U2 > &otherone) {}
};
}
%}
%include <std_string.i>
namespace Standard {
%template(StringPair) Pair<std::string, std::string>;
%template(ShortPair) Pair<short, short>;
%template(IntPair) Pair<int, int>;
%template(DoublePair) Pair<double, double>;
%extend Pair<int, int> {
// Templated constructor which uses 'correct' name of the containing class (IntPair)
%template(IntPair) Pair<short, short>;
// Templated constructors that behave differently in different languages as the template name
// does not match IntPair, the instantiated name for Pair<int, int>.
// Some languages wrap as a factory style function (Python),
// others ignore the name and wrap as regular constructor (Java).
%template(Pair) Pair<double, double>;
%template(MakeStringPair) Pair<std::string, std::string>;
}
}

View File

@ -224,25 +224,16 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri
} }
} }
} else if (Equal(nodeType, "constructor")) { } else if (Equal(nodeType, "constructor")) {
String *name = Getattr(n, "name");
if (!(Getattr(n, "templatetype"))) { if (!(Getattr(n, "templatetype"))) {
String *symname; String *symname = Getattr(n, "sym:name");
String *stripped_name = SwigType_templateprefix(name); String *name;
if (Strstr(tname, stripped_name)) {
Replaceid(name, stripped_name, tname);
}
Delete(stripped_name);
symname = Getattr(n, "sym:name");
if (symname) { if (symname) {
stripped_name = SwigType_templateprefix(symname); String *stripped_name = SwigType_templateprefix(symname);
if (Strstr(tname, stripped_name)) { if (Strstr(tname, stripped_name)) {
Replaceid(symname, stripped_name, tname); Replaceid(symname, stripped_name, tname);
} }
Delete(stripped_name); Delete(stripped_name);
} }
if (strchr(Char(name), '<')) {
Append(patchlist, Getattr(n, "name"));
}
name = Getattr(n, "sym:name"); name = Getattr(n, "sym:name");
if (name) { if (name) {
if (strchr(Char(name), '<')) { if (strchr(Char(name), '<')) {
@ -266,21 +257,9 @@ static void cparse_template_expand(Node *templnode, Node *n, String *tname, Stri
* template node, with the special exception for %extend which adds its methods under an intermediate node. */ * template node, with the special exception for %extend which adds its methods under an intermediate node. */
Node* parent = parentNode(n); Node* parent = parentNode(n);
if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) { if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) {
String *name = Getattr(n, "name"); String *symname = Getattr(n, "sym:name");
if (name) { if (symname)
if (strchr(Char(name), '<')) Replace(symname, tname, rname, DOH_REPLACE_ANY);
Append(patchlist, Getattr(n, "name"));
}
name = Getattr(n, "sym:name");
if (name) {
if (strchr(Char(name), '<')) {
String *sn = Copy(tname);
Setattr(n, "sym:name", sn);
Delete(sn);
} else {
Replace(name, tname, rname, DOH_REPLACE_ANY);
}
}
Append(cpatchlist, Getattr(n, "code")); Append(cpatchlist, Getattr(n, "code"));
} }
} else if (Equal(nodeType, "using")) { } else if (Equal(nodeType, "using")) {
@ -478,7 +457,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
List *patchlist, *cpatchlist, *typelist; List *patchlist, *cpatchlist, *typelist;
String *templateargs; String *templateargs;
String *tname; String *tname;
String *iname; String *name_with_templateargs = 0;
String *tbase; String *tbase;
Parm *unexpanded_variadic_parm = 0; Parm *unexpanded_variadic_parm = 0;
ParmList *expanded_variadic_parms = 0; ParmList *expanded_variadic_parms = 0;
@ -551,9 +530,12 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
{ {
String *name = Getattr(n, "name"); String *name = Getattr(n, "name");
if (name) { if (name) {
Append(name, templateargs); String *nodeType = nodeType(n);
name_with_templateargs = NewStringf("%s%s", name, templateargs);
if (!(Equal(nodeType, "constructor") || Equal(nodeType, "destructor"))) {
Setattr(n, "name", name_with_templateargs);
}
} }
iname = name;
} }
/* Patch all of the types */ /* Patch all of the types */
@ -609,12 +591,12 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
Node *tynode = Swig_symbol_clookup(s, 0); Node *tynode = Swig_symbol_clookup(s, 0);
String *tyname = tynode ? Getattr(tynode, "sym:name") : 0; String *tyname = tynode ? Getattr(tynode, "sym:name") : 0;
/* /*
Printf(stdout, " replacing %s with %s to %s or %s to %s\n", s, name, dvalue, tbase, iname); Printf(stdout, " replacing %s with %s to %s or %s to %s\n", s, name, dvalue, tbase, name_with_templateargs);
Printf(stdout, " %d %s to %s\n", tp == unexpanded_variadic_parm, name, ParmList_str_defaultargs(expanded_variadic_parms)); Printf(stdout, " %d %s to %s\n", tp == unexpanded_variadic_parm, name, ParmList_str_defaultargs(expanded_variadic_parms));
*/ */
if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) { if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) {
SwigType_typename_replace(s, name, dvalue); SwigType_typename_replace(s, name, dvalue);
SwigType_typename_replace(s, tbase, iname); SwigType_typename_replace(s, tbase, name_with_templateargs);
} }
} }
@ -645,7 +627,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
String *s = Getitem(typelist, i); String *s = Getitem(typelist, i);
assert(!SwigType_isvariadic(s)); /* All parameters should have already been expanded, this is for function that contain variadic parameters only, such as f(v.p.V) */ assert(!SwigType_isvariadic(s)); /* All parameters should have already been expanded, this is for function that contain variadic parameters only, such as f(v.p.V) */
SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms); SwigType_variadic_replace(s, unexpanded_variadic_parm, expanded_variadic_parms);
SwigType_typename_replace(s, tbase, iname); SwigType_typename_replace(s, tbase, name_with_templateargs);
} }
} }
} }
@ -664,6 +646,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
} }
} }
} }
Delete(name_with_templateargs);
Delete(patchlist); Delete(patchlist);
Delete(cpatchlist); Delete(cpatchlist);
Delete(typelist); Delete(typelist);
@ -671,7 +654,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
Delete(tname); Delete(tname);
Delete(templateargs); Delete(templateargs);
/* set_nodeType(n,"template"); */
return 0; return 0;
} }

View File

@ -2555,13 +2555,18 @@ int Language::constructorDeclaration(Node *n) {
return SWIG_NOWRAP; return SWIG_NOWRAP;
} }
/* Name adjustment for %rename */ // Name adjustment of constructor when a class has been renamed with %rename
Swig_save("constructorDeclaration", n, "sym:name", NIL); Swig_save("constructorDeclaration", n, "sym:name", NIL);
{ {
String *base = Swig_scopename_last(name); String *base = Swig_scopename_last(name);
if ((Strcmp(base, symname) == 0) && (Strcmp(symname, ClassPrefix) != 0)) { // Note that it is possible for the constructor to have a different name to the class name in
Setattr(n, "sym:name", ClassPrefix); // some target languages, where it is wrapped as a factory type function instead of a constructor.
if (Equal(base, symname) && !Equal(symname, ClassPrefix)) {
// Adjust name, except when the constructor's name comes from a templated constructor,
// where the name passed to %template is used instead.
if (!Getattr(n, "template"))
Setattr(n, "sym:name", ClassPrefix);
} }
Delete(base); Delete(base);
} }