File: template_partial_specialization_more.i

package info (click to toggle)
swig 4.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 46,232 kB
  • sloc: cpp: 54,631; ansic: 29,122; java: 17,530; python: 12,505; cs: 10,369; ruby: 7,232; yacc: 6,477; makefile: 5,965; javascript: 5,520; sh: 5,415; perl: 4,187; php: 3,693; ml: 2,187; lisp: 2,056; tcl: 1,991; xml: 115
file content (142 lines) | stat: -rw-r--r-- 5,417 bytes parent folder | download | duplicates (2)
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);
}
%}