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 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> {
%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")) {
String *name = Getattr(n, "name");
if (!(Getattr(n, "templatetype"))) {
String *symname;
String *stripped_name = SwigType_templateprefix(name);
if (Strstr(tname, stripped_name)) {
Replaceid(name, stripped_name, tname);
}
Delete(stripped_name);
symname = Getattr(n, "sym:name");
String *symname = Getattr(n, "sym:name");
String *name;
if (symname) {
stripped_name = SwigType_templateprefix(symname);
String *stripped_name = SwigType_templateprefix(symname);
if (Strstr(tname, stripped_name)) {
Replaceid(symname, stripped_name, tname);
}
Delete(stripped_name);
}
if (strchr(Char(name), '<')) {
Append(patchlist, Getattr(n, "name"));
}
name = Getattr(n, "sym:name");
if (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. */
Node* parent = parentNode(n);
if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) {
String *name = Getattr(n, "name");
if (name) {
if (strchr(Char(name), '<'))
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);
}
}
String *symname = Getattr(n, "sym:name");
if (symname)
Replace(symname, tname, rname, DOH_REPLACE_ANY);
Append(cpatchlist, Getattr(n, "code"));
}
} 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;
String *templateargs;
String *tname;
String *iname;
String *name_with_templateargs = 0;
String *tbase;
Parm *unexpanded_variadic_parm = 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");
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 */
@ -609,12 +591,12 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
Node *tynode = Swig_symbol_clookup(s, 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));
*/
if (!tyname || !tsname || !Equal(tyname, tsname) || Getattr(tynode, "templatetype")) {
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);
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_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(cpatchlist);
Delete(typelist);
@ -671,7 +654,6 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
Delete(tname);
Delete(templateargs);
/* set_nodeType(n,"template"); */
return 0;
}

View File

@ -2555,12 +2555,17 @@ int Language::constructorDeclaration(Node *n) {
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);
{
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
// 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);