diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2023-03-01 18:34:09 +0000 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2023-03-01 19:42:00 +0000 |
commit | 9924c5c3e14f24896351a26064ab22aa0a024a4a (patch) | |
tree | ba561ddefa1e4120c134ef6e123ba1199b02616d /Examples | |
parent | a55e429bf297d7daddf0bef3a3dc5832f433aef0 (diff) | |
download | swig-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')
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); +} +%} |