op | opfunc |
---|---|
- | neg |
~ | com |
e++ | postinc |
e-- | postdec |
Given a unary overloadable operator op and its corresponding class or struct member function name opfunc, the syntax:
op awhere a is a class or struct object reference, is interpreted as if it was written as:
a.opfunc()
class A { int neg(); } A a; -a; // equivalent to a.neg();
class A { int neg(int i); } A a; -a; // equivalent to a.neg(), which is an error
op | commutative? | opfunc | opfunc_r |
---|---|---|---|
+ | yes | add | - |
- | no | sub | sub_r |
* | yes | mul | - |
/ | no | div | div_r |
% | no | mod | mod_r |
& | yes | and | - |
| | yes | or | - |
^ | yes | xor | - |
<< | no | shl | shl_r |
>> | no | shr | shr_r |
>>> | no | ushr | ushr_r |
~ | no | cat | cat_r |
== | yes | eq | - |
!= | yes | eq | - |
< | yes | cmp | - |
<= | yes | cmp | - |
> | yes | cmp | - |
>= | yes | cmp | - |
+= | no | addass | - |
-= | no | subass | - |
*= | no | mulass | - |
/= | no | divass | - |
%= | no | modass | - |
&= | no | andass | - |
|= | no | orass | - |
^= | no | xorass | - |
<<= | no | shlass | - |
>>= | no | shrass | - |
>>>= | no | ushrass | - |
~= | no | catass | - |
Given a binary overloadable operator op and its corresponding class or struct member function name opfunc and opfunc_r, the syntax:
a op bis interpreted as if it was written as:
a.opfunc(b)or:
b.opfunc_r(a)The following sequence of rules is applied, in order, to determine which form is used:
a.opfunc(b)
b.opfunc_r(a)
b.opfunc(a)
class A { int add(int i); } A a; a + 1; // equivalent to a.add(1)
1 + a; // equivalent to a.add(1)
class B { int div_r(int i); } B b; 1 / b; // equivalent to b.div_r(1)
The member function eq() is defined as part of Object as:
int eq(Object o);so that every class object has an eq().
If a struct has no eq() function declared for it, a bit compare of the contents of the two structs is done to determine equality or inequality.
The member function cmp() is defined as part of Object as:
int cmp(Object o);so that every class object has a cmp().
If a struct has no cmp() function declared for it, attempting to compare two structs is an error.
Note: Comparing a reference to a class object against null should be done as:
if (a === null)and not as:
if (a == null)The latter is converted to:
if (a.cmp(null))which will fail if cmp() is a virtual function.
class A { int cmp(Object o) { assert(0); // comparison makes no sense return 0; } }
struct F { int opCall(); int opCall(int x, int y, int z); } void test() { F f; int i; i = f(); // same as i = f.opCall(); i = f(3,4,5); // same as i = a.opCall(3,4,5); }In this way a struct or class object can behave as if it were a function.
struct A { int opIndex(int i); int opIndex(int i, int value); } void test() { A a; int i; i = a[5]; // same as i = a.opIndex(5); a[i] = 7; // same as a.opIndex(i,7); }In this way a struct or class object can behave as if it were an array.
Note: Array index overloading currently does not work for the lvalue of an op=, ++, or -- operator.
class A { int opSlice(); // overloads a[] int opSlice(int x, int y); // overloads a[i .. j] } void test() { A a = new A(); int i; i = a[]; // same as i = a.opSlice(); i = a[3..4]; // same as i = a.opSlice(3,4); }