· Lexical · Modules · Declarations · Types · Properties · Attributes · Pragmas · Expressions · Statements · Arrays · Structs & Unions · Classes · Interfaces · Enums · Functions · Operator Overloading · Templates · Mixins · Contracts · Conditional Compilation · Handling errors · Garbage Collection · Memory Management · Floating Point · Inline Assembler · Interfacing To C · Portability Guide · Embedding D in HTML · Named Character Entities · Application Binary Interface |
Operator OverloadingOverloading is accomplished by interpreting specially named struct and class member functions as being implementations of unary and binary operators. No additional syntax is used.Unary Operator OverloadingOverloadable Unary Operators
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() Overloading ++e and --eSince ++e is defined to be semantically equivalent to (e += 1), the expression ++e is rewritten as (e += 1), and then checking for operator overloading is done. The situation is analogous for --e.Examples
Overloading cast(type)eThe member function e.opCast() is called, and the return value of opCast() is implicitly converted to type. Since functions cannot be overloaded based on return value, there can be only one opCast per struct or class. Overloading the cast operator does not affect implicit casts, it only applies to explicit casts.struct A { int opCast() { return 28; } } void test() { A a; long i = cast(long)a; // i is set to 28L void* p = cast(void*)a; // error, cannot implicitly // convert int to void* int j = a; // error, cannot implicitly convert // A to int } Binary Operator OverloadingOverloadable Binary Operators
Given a binary overloadable operator op and its corresponding class or struct member function name opfunc and opfunc_r, and the syntax: a op bthe following sequence of rules is applied, in order, to determine which form is used:
Examples
Overloading == and !=Both operators use the opEquals() function. The expression (a == b) is rewritten as a.opEquals(b), and (a != b) is rewritten as !a.opEquals(b).The member function opEquals() is defined as part of Object as: int opEquals(Object o);so that every class object has an opEquals(). If a struct has no opEquals() function declared for it, a bit compare of the contents of the two structs is done to determine equality or inequality. Overloading <, <=, > and >=These comparison operators all use the opCmp() function. The expression (a op b) is rewritten as (a.opCmp(b) op 0). The commutative operation is rewritten as (0 op b.opCmp(a))The member function opCmp() is defined as part of Object as: int opCmp(Object o);so that every class object has a opCmp(). If a struct has no opCmp() 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.opCmp(null))which will fail if opCmp() is a virtual function. RationaleThe reason for having both opEquals() and opCmp() is that:
Function Call Operator Overloading f()The function call operator, (), can be overloaded by declaring a function named opCall: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. Array Operator OverloadingOverloading Indexing a[i]The array index operator, [], can be overloaded by declaring a function named opIndex with one or more parameters. Assignment to an array can be overloaded with a function named opIndexAssign with two or more parameters. The first parameter is the rvalue of the assignment expression.struct A { int opIndex(int i1, int i2, int i3); int opIndexAssign(int value, int i1, int i2); } void test() { A a; int i; i = a[5,6,7]; // same as i = a.opIndex(5,6,7); a[i,3] = 7; // same as a.opIndexAssign(7,i,3); }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. Overloading Slicing a[] and a[i .. j]Overloading the slicing operator means overloading expressions like a[] and a[i .. j].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); } Future DirectionsThe operators ., &&, ||, ?:, and a few others will likely never be overloadable. The names of the overloaded operators may change. |
Add feedback and comments regarding this page.