Operator Overloading
C3 allows some limited operator overloading for working with containers.
”Element at” operator []
Implementing []
allows a type to use the my_type[<value>]
syntax:
struct Foo{ double[] x;}
fn double Foo.get(&self, usz i) @operator([]){ return self.x[i];}
It’s possible to use any type as argument, such as a string:
fn double Bar.get(&self, String str) @operator([]){ return self.get_val_by_key(str);}
Only a single [] overload is allowed.
”Element ref” operator &[]
Similar to [], the operator returns a value for &my_type[<value>]
, which may
be retrieved in a different way. If this overload isn’t defined, then &my_type[<value>]
would
be a syntax error.
fn double* Foo.get_ref(&self, usz i) @operator(&[]){ return &self.x[i];}
”Element set” operator []=
The counterpart of [] allows setting an element using my_type[<index>] = <value>
.
fn void Foo.set(&self, usz i, double new_val) @operator([]=){ return self.x[i] = new_val;}
”len” operator
Unlike the previous operator overloads, the “len” operator simply enables functionality
which augments the []
-family of operators: you can use the “from end” syntax e.g my_type[^1]
to get the last element assuming the indexing uses integers.
Enabling ‘foreach’
In order to use a type with foreach, e.g. foreach(d : foo)
, at a minimum methods
with overloads for []
(@operator([])
) and len
(@operator(len)
) need to be added.
If &[]
is implemented, foreach by reference is enabled (e.g. foreach(double* &d : foo)
)
fn double Foo.get(&self, usz i) @operator([]){ return self.x[i];}
fn usz Foo.len(&self) @operator(len){ return self.x.len;}
fn void test(Foo f){ // Print all elements in f foreach (d : f) { io::printfn("%f", d); }}