1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
%module template_partial_specialization_more
// (1) Based on https://stackoverflow.com/questions/9757642/wrapping-specialised-c-template-class-with-swig
%inline %{
template<typename V> struct Vect {};
template<class T, typename TT>
class Foo {
public:
Foo() {}
virtual ~Foo() {}
T primary() const { return T(); }
};
template<class TS, typename TTS>
class Foo<Vect<TS>, TTS> {
public:
Foo() {}
virtual ~Foo() {}
TS partially_specialized(TS parmin) const { return parmin; }
};
template<>
class Foo<Vect<double>, double> {
public:
Foo() {}
virtual ~Foo() {}
double value_fully_specialized(double d) const { return d; }
};
template<class T, typename TT>
class Foo<T*, TT> {
public:
Foo() {}
virtual ~Foo() {}
int pointer_specialize(T myT) const { return 0; }
};
%}
%template(VectInt) Vect<int>;
%template(FooVectIntDouble) Foo<Vect<int>, double>; // was failing
%template(FooShortPtrDouble) Foo<short*, double>;
%template(FooVectVectInt) Foo<Vect<Vect<int> >, int>; // was failing
// (2) Same types in both args
%inline %{
template<typename X, typename Y> struct Hey { void primary() {} };
template<typename T> struct Hey<T, T> { void special_hey() {} };
%}
%template(HeyInts) Hey<int, int>; // was failing, was calling primary
// (3) Partial specialization using one template parameter instead of two
%inline %{
struct PlainStruct {};
template <typename T, typename U> struct XX { void primary() {} };
template <typename T> struct XX<T, T &> { void special1() {} }; // r.$1
template <typename T> struct XX<T, T const&> { void special2() {} }; // r.q(const).$1
template <typename T> struct XX<T, T *const&> { void special3() {} }; // r.q(const).p.$1
%}
%template(XX1) XX<int, int&>; // was failing, was calling primary
%template(XX2) XX<int, int const&>;
%template(XX3) XX<PlainStruct, PlainStruct *const&>;
// (4) Switching parameters around
%inline %{
#include <iostream>
template<typename P1 = int, typename P2 = double> struct Partialler { void primary(P1, P2) {}; };
template<typename S1, typename S2> struct Partialler<S2, S1*> { void special(S1*, S2, bool) {}; };
%}
%template(PartiallerPrimary) Partialler<short, short>;
%template(PartiallerSpecial) Partialler<int, PlainStruct*>;
// (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) {} };
template <typename TTTT> struct Lyst<const TTTT&> { void specialized3(TTTT) {} };
void test_list() {
double mydouble = 0;
short myshort = 0;
Lyst<double>().primary(mydouble, Allocator<double>());
Lyst<short, Allocator<short> >().primary(myshort, Allocator<short>());
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(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);
}
%}
|