summaryrefslogtreecommitdiff
path: root/Examples/test-suite/operator_overload.i
blob: 80facff766b67d320065fa9927e6af5eecc319ac (plain)
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/* File : operator_overload.i */
/*
This is a test of all the possible operator overloads

see bottom for a set of possible tests
*/
%module operator_overload

#if defined(SWIGPYTHON)
%warnfilter(SWIGWARN_IGNORE_OPERATOR_EQ,
	    SWIGWARN_IGNORE_OPERATOR_INDEX,
	    SWIGWARN_IGNORE_OPERATOR_PLUSPLUS,
	    SWIGWARN_IGNORE_OPERATOR_MINUSMINUS,
	    SWIGWARN_IGNORE_OPERATOR_LAND,
	    SWIGWARN_IGNORE_OPERATOR_LOR);
#endif

#if !defined(SWIGLUA) && !defined(SWIGR)
%rename(Equal) operator =;
%rename(PlusEqual) operator +=;
%rename(MinusEqual) operator -=;
%rename(MultiplyEqual) operator *=;
%rename(DivideEqual) operator /=;
%rename(PercentEqual) operator %=;
%rename(Plus) operator +;
%rename(Minus) operator -;
%rename(Multiply) operator *;
%rename(Divide) operator /;
%rename(Percent) operator %;
%rename(Not) operator !;
%rename(IndexIntoConst) operator[](unsigned idx) const;
%rename(IndexInto) operator[](unsigned idx);
%rename(Functor) operator ();
%rename(EqualEqual) operator ==;
%rename(NotEqual) operator !=;
%rename(LessThan) operator <;
%rename(LessThanEqual) operator <=;
%rename(GreaterThan) operator >;
%rename(GreaterThanEqual) operator >=;
%rename(And) operator &&;
%rename(Or) operator ||;
%rename(PlusPlusPrefix) operator++();
%rename(PlusPlusPostfix) operator++(int);
%rename(MinusMinusPrefix) operator--();
%rename(MinusMinusPostfix) operator--(int);
#endif

%rename(IndexInto) *::operator[](unsigned idx); // some languages have a %rename *::operator[] already in place, which seems to takes precedence over the above %rename operator[].

#ifdef SWIGCSHARP
%csmethodmodifiers operator++() "protected";
%csmethodmodifiers operator++(int) "private";
%csmethodmodifiers operator--() "private";
%csmethodmodifiers operator--(int) "protected";
%typemap(cscode) Op %{
  public static Op operator++(Op op) {
    // Unlike C++, operator++ must not modify the parameter and both prefix and postfix operations call this method
    Op newOp = new Op(op.i);
    newOp.PlusPlusPostfix(0);
    return newOp;
  }
  public static Op operator--(Op op) {
    // Unlike C++, operator-- must not modify the parameter and both prefix and postfix operations call this method
    Op newOp = new Op(op.i);
    newOp.MinusMinusPrefix();
    return newOp;
  }
%}
#endif

#ifdef SWIGPHP
%rename(AndOperator) operator &&;
%rename(OrOperator) operator ||;
#endif

#ifdef SWIG_ALLEGRO_CL
%{
#include <stdio.h>
%}
#endif

%rename(IntCast) operator int();
%rename(DoubleCast) operator double();

%inline %{

#if defined(_MSC_VER)
  #include <iso646.h> /* for named logical operator, eg 'operator or' */
#endif

#include <assert.h>

class Op {
public:
  int i;
  Op(int a=0) : i(a)
  {}
  Op(const Op& o) : i(o.i)
  {}
  virtual ~Op()
  {}

  friend Op operator &&(const Op& a,const Op& b){return Op(a.i&&b.i);}
  friend Op operator or(const Op& a,const Op& b){return Op(a.i||b.i);}

  Op &operator=(const Op& o) {
    i=o.i;
    return *this;
  }
  // +=,-=... are member fns
  void operator+=(const Op& o){ i+=o.i;}
  void operator-=(const Op& o){ i-=o.i;}
  void operator*=(const Op& o){ i*=o.i;}
  void operator/=(const Op& o){ i/=o.i;}
  void operator%=(const Op& o){ i%=o.i;}
  // the +,-,*,... are friends
  // (just to make life harder)
  friend Op operator+(const Op& a,const Op& b){return Op(a.i+b.i);}
  friend Op operator-(const Op& a,const Op& b);
  friend Op operator*(const Op& a,const Op& b){return Op(a.i*b.i);}
  friend Op operator/(const Op& a,const Op& b){return Op(a.i/b.i);}
  friend Op operator%(const Op& a,const Op& b){return Op(a.i%b.i);}

  // unary operators
  Op operator-() const {return Op(-i);}
  bool operator !() const {return !(i);}

  // overloading the [] operator
  // need 2 versions: get & set
  // note: C++ can be a little mixed up upon which version it calls
  // most of the time it calls the second version
  int operator[](unsigned idx)const
  {	  if (idx==0) return i; return 0;}
  int& operator[](unsigned idx)
  {	  if (idx==0) return i; static int j;j=0; return j;}

  // overloading the () operator
  // this can have many parameters so we will test this
  int operator()(int a=0){return i+a;}
  int operator()(int a,int b){return i+a+b;}

  // increment/decrement operators
  Op& operator++() {++i; return *this;} // prefix ++
  Op operator++(int) {Op o = *this; ++(*this); return o;} // postfix ++
  Op& operator--() {--i; return *this;} // prefix --
  Op operator--(int) {Op o = *this; --(*this); return o;} // postfix --

  // TODO: <<,<<=

  // cast operators
  operator double() { return i; }
  virtual operator int() { return i; }

  // This method just checks that the operators are implemented correctly
  static void sanity_check();
};

// just to complicate matters
// we have a couple of non class operators
inline bool operator==(const Op& a,const Op& b){return a.i==b.i;}
inline bool operator!=(const Op& a,const Op& b){return a.i!=b.i;}
inline bool operator< (const Op& a,const Op& b){return a.i<b.i;}
inline bool operator<=(const Op& a,const Op& b){return a.i<=b.i;}
inline bool operator> (const Op& a,const Op& b){return a.i>b.i;}
inline bool operator>=(const Op& a,const Op& b){return a.i>=b.i;}

%}

%{
  // This one is not declared inline as VC++7.1 gets mixed up with the unary operator-
  Op operator-(const Op& a,const Op& b){return Op(a.i-b.i);}
%}

// in order to wrapper this correctly
// we need to extend the class
// to make the friends & non members part of the class
%extend Op{
        Op operator &&(const Op& b){return Op($self->i&&b.i);}
        Op operator or(const Op& b){return Op($self->i||b.i);}

	Op operator+(const Op& b){return Op($self->i+b.i);}
	Op operator-(const Op& b){return Op($self->i-b.i);}
	Op operator*(const Op& b){return Op($self->i*b.i);}
	Op operator/(const Op& b){return Op($self->i/b.i);}
	Op operator%(const Op& b){return Op($self->i%b.i);}

	bool operator==(const Op& b){return $self->i==b.i;}
	bool operator!=(const Op& b){return $self->i!=b.i;}
	bool operator< (const Op& b){return $self->i<b.i;}
	bool operator<=(const Op& b){return $self->i<=b.i;}
	bool operator> (const Op& b){return $self->i>b.i;}
	bool operator>=(const Op& b){return $self->i>=b.i;}

	// subtraction with reversed arguments
	Op __rsub__(const int b){return Op(b - $self->i);}

	// we also add the __str__() fn to the class
	// this allows it to be converted to a string (so it can be printed)
	const char* __str__()
	{
		static char buffer[255];
		sprintf(buffer,"Op(%d)",$self->i);
		return buffer;
	}
	// to get the [] operator working correctly we need to extend with two function
	// __getitem__ & __setitem__
	int __getitem__(unsigned i)
	{	return (*$self)[i];	}
	void __setitem__(unsigned i,int v)
	{	(*$self)[i]=v;	}
}

/*
Suggested list of operator overloads (mainly from python)

Operators overloaded with their C++ equivalent
__add__,__sub__,__mul__,__div__,__mod__	+,-,*,/,%
__iadd__,__isub__,__imul__,__idiv__,__imod__	+=,-=,*=,/=,%=

__eq__,__ne__,__lt__,__le__,__gt__,__ge__ ==,!=,<,<=,>,>=
__not__,__neg__	unary !, unary -
__and__,__or__,__xor__	logical and,logical or,logical xor
__rshift__,__lshift__ >>,<<

__getitem__,__setitem__ for operator[]

Operators overloaded without C++ equivilents
__pow__ for power operator
__str__ converts object to a string (should return a const char*)
__concat__ for contatenation (if language supports)

*/

%inline %{
class OpDerived : public Op {
public:
  OpDerived(int a=0) : Op(a)
  {}

  // overloaded
  virtual operator int() { return i*2; }
};
%}


%{

#include <assert.h>

void Op::sanity_check()
{
	// test routine:
	Op a;
	Op b=5;
	Op c=b;	// copy construct
	Op d=2;
        Op dd=d; // assignment operator

	// test equality
	assert(a!=b);
	assert(b==c);
	assert(a!=d);
        assert(d==dd);

	// test <
	assert(a<b);
	assert(a<=b);
	assert(b<=c);
	assert(b>=c);
	assert(b>d);
	assert(b>=d);

	// test +=
	Op e=3;
	e+=d;
	assert(e==b);
	e-=c;
	assert(e==a);
	e=Op(1);
	e*=b;
	assert(e==c);
	e/=d;
	assert(e==d);
	e%=c;
	assert(e==d);

	// test +
	Op f(1),g(1);
	assert(f+g==Op(2));
	assert(f-g==Op(0));
	assert(f*g==Op(1));
	assert(f/g==Op(1));
	assert(f%g==Op(0));

	// test unary operators
	assert(!a==true);
	assert(!b==false);
	assert(-a==a);
	assert(-b==Op(-5));

	// test []
	Op h=3;
	assert(h[0]==3);
	assert(h[1]==0);
	h[0]=2;	// set
	assert(h[0]==2);
	h[1]=2;	// ignored
	assert(h[0]==2);
	assert(h[1]==0);

	// test ()
	Op i=3;
	assert(i()==3);
	assert(i(1)==4);
	assert(i(1,2)==6);

	// plus add some code to check the __str__ fn
	//assert(str(Op(1))=="Op(1)");
	//assert(str(Op(-3))=="Op(-3)");

        // test ++ and --
        Op j(100);
        int original = j.i;
        {
          Op newOp = j++;
          int newInt = original++;
          assert(j.i == original);
          assert(newOp.i == newInt);
        }
        {
          Op newOp = j--;
          int newInt = original--;
          assert(j.i == original);
          assert(newOp.i == newInt);
        }
        {
          Op newOp = ++j;
          int newInt = ++original;
          assert(j.i == original);
          assert(newOp.i == newInt);
        }
        {
          Op newOp = --j;
          int newInt = --original;
          assert(j.i == original);
          assert(newOp.i == newInt);
        }

        // cast operators
        Op k=3;
        int check_k = k;
        assert (check_k == 3);

        Op l=4;
        double check_l = l;
        assert (check_l == 4);
}

%}