summaryrefslogtreecommitdiff
path: root/Examples
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2023-03-01 18:34:09 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2023-03-01 19:42:00 +0000
commit9924c5c3e14f24896351a26064ab22aa0a024a4a (patch)
treeba561ddefa1e4120c134ef6e123ba1199b02616d /Examples
parenta55e429bf297d7daddf0bef3a3dc5832f433aef0 (diff)
downloadswig-9924c5c3e14f24896351a26064ab22aa0a024a4a.tar.gz
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>;
Diffstat (limited to 'Examples')
-rw-r--r--Examples/test-suite/errors/cpp_template_partial_specialization_defaults.i9
-rw-r--r--Examples/test-suite/errors/cpp_template_partial_specialization_defaults.stderr2
-rw-r--r--Examples/test-suite/java/template_partial_specialization_more_runme.java49
-rw-r--r--Examples/test-suite/template_partial_specialization_more.i68
4 files changed, 113 insertions, 15 deletions
diff --git a/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.i b/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.i
new file mode 100644
index 000000000..25b2c5c36
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.i
@@ -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>;
diff --git a/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.stderr b/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.stderr
new file mode 100644
index 000000000..196862431
--- /dev/null
+++ b/Examples/test-suite/errors/cpp_template_partial_specialization_defaults.stderr
@@ -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.
diff --git a/Examples/test-suite/java/template_partial_specialization_more_runme.java b/Examples/test-suite/java/template_partial_specialization_more_runme.java
new file mode 100644
index 000000000..c990a1bc0
--- /dev/null
+++ b/Examples/test-suite/java/template_partial_specialization_more_runme.java
@@ -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);
+ }
+}
diff --git a/Examples/test-suite/template_partial_specialization_more.i b/Examples/test-suite/template_partial_specialization_more.i
index a9e0a591b..e63ac158b 100644
--- a/Examples/test-suite/template_partial_specialization_more.i
+++ b/Examples/test-suite/template_partial_specialization_more.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
+%include <std_string.i>
%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 *>());
+template <typename TTTT> struct Lyst<const TTTT&> { void specialized3(TTTT) {} };
+void test_list() {
double mydouble = 0;
- Lyst<double **> lissd;
- lissd.specialized2(mydouble, (double **)0);
+ Lyst<double>().primary(mydouble, Allocator<double>());
+ Lyst<short, Allocator<short> >().primary(mydouble, Allocator<short>());
-// Lyst<const int&> lissconstint;
-// lissconstint.specialized3(myint);
+ PlainStruct ps;
+ int myint = 0;
+ std::string mystring = 0;
+ Lyst<PlainStruct *>().specialized1(ps, Allocator<PlainStruct *>());
+ Lyst<double **>().specialized2(mydouble, (double **)0);
+ Lyst<const int&>().specialized3(myint);
+ // Specifying the default still calls the partially specialized template
+ Lyst<std::string const &, Allocator<std::string const &> >().specialized3(mystring);
}
%}
+%template(AllocatorDouble) Allocator<double>;
+%template(AllocatorShort) Allocator<short>;
+%template(AllocatorPlainStructPtr) Allocator<PlainStruct *>;
+
%template(LystDouble) Lyst<double>;
-//%template(LystDouble) Lyst<short, Allocator<short> >;
+%template(LystShort) Lyst<short, Allocator<short> >;
%template(LystPlainStructPtr) Lyst<PlainStruct *>;
%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);
+}
+%}