| 1 | //! Provides a macro to simplify operator overloading.
|
| 2 | //!
|
| 3 | //! To use, include the following:
|
| 4 | //! ```
|
| 5 | //! extern crate overload;
|
| 6 | //! use overload::overload;
|
| 7 | //! use std::ops; // <- don't forget this or you'll get nasty errors
|
| 8 | //! ```
|
| 9 | //!
|
| 10 | //! # Introduction
|
| 11 | //!
|
| 12 | //! Suppose we have the following `struct` definition:
|
| 13 | //! ```
|
| 14 | //! #[derive(PartialEq, Debug)]
|
| 15 | //! struct Val {
|
| 16 | //! v: i32
|
| 17 | //! }
|
| 18 | //! ```
|
| 19 | //! We can overload the addition of `Val`s like so:
|
| 20 | //! ```
|
| 21 | //! # extern crate overload;
|
| 22 | //! # use overload::overload;
|
| 23 | //! # use std::ops;
|
| 24 | //! # #[derive(PartialEq, Debug)]
|
| 25 | //! # struct Val {
|
| 26 | //! # v: i32
|
| 27 | //! # }
|
| 28 | //! overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
|
| 29 | //! ```
|
| 30 | //! The macro call above generates the following code:
|
| 31 | //! ```ignore
|
| 32 | //! impl ops::Add<Val> for Val {
|
| 33 | //! type Output = Val;
|
| 34 | //! fn add(self, b: Val) -> Self::Output {
|
| 35 | //! let a = self;
|
| 36 | //! Val { v: a.v + b.v }
|
| 37 | //! }
|
| 38 | //! }
|
| 39 | //! ```
|
| 40 | //! We are now able to add `Val`s:
|
| 41 | //! ```
|
| 42 | //! # extern crate overload;
|
| 43 | //! # use overload::overload;
|
| 44 | //! # use std::ops;
|
| 45 | //! # #[derive(PartialEq, Debug)]
|
| 46 | //! # struct Val {
|
| 47 | //! # v: i32
|
| 48 | //! # }
|
| 49 | //! # overload!((a: Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
|
| 50 | //! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
|
| 51 | //! ```
|
| 52 | //!
|
| 53 | //! # Owned and borrowed types
|
| 54 | //!
|
| 55 | //! If we also wanted to overload addition for the borrowed type `&Val` we could write:
|
| 56 | //! ```
|
| 57 | //! # extern crate overload;
|
| 58 | //! # use overload::overload;
|
| 59 | //! # use std::ops;
|
| 60 | //! # #[derive(PartialEq, Debug)]
|
| 61 | //! # struct Val {
|
| 62 | //! # v: i32
|
| 63 | //! # }
|
| 64 | //! overload!((a: &Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
|
| 65 | //! ```
|
| 66 | //! We might also want to overload addition between the owned and borrowed types:
|
| 67 | //! ```
|
| 68 | //! # extern crate overload;
|
| 69 | //! # use overload::overload;
|
| 70 | //! # use std::ops;
|
| 71 | //! # #[derive(PartialEq, Debug)]
|
| 72 | //! # struct Val {
|
| 73 | //! # v: i32
|
| 74 | //! # }
|
| 75 | //! overload!((a: Val) + (b: &Val) -> Val { Val { v: a.v + b.v } });
|
| 76 | //! overload!((a: &Val) + (b: Val) -> Val { Val { v: a.v + b.v } });
|
| 77 | //! ```
|
| 78 | //! Let's see how we can write these combinations more concisely.
|
| 79 | //!
|
| 80 | //! We can include a `?` in front of a type to indicate that it should stand in for both the owned and borrowed type.
|
| 81 | //!
|
| 82 | //! To overload addition for all four combinations between `Val` and `&Val` we can therefore simply include a `?` in front of both types:
|
| 83 | //! ```
|
| 84 | //! # extern crate overload;
|
| 85 | //! # use overload::overload;
|
| 86 | //! # use std::ops;
|
| 87 | //! # #[derive(PartialEq, Debug)]
|
| 88 | //! # struct Val {
|
| 89 | //! # v: i32
|
| 90 | //! # }
|
| 91 | //! overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
|
| 92 | //! ```
|
| 93 | //! The macro call above generates the following code:
|
| 94 | //! ```ignore
|
| 95 | //! impl ops::Add<Val> for Val {
|
| 96 | //! type Output = Val;
|
| 97 | //! fn add(self, b: Val) -> Self::Output {
|
| 98 | //! let a = self;
|
| 99 | //! Val { v: a.v + b.v }
|
| 100 | //! }
|
| 101 | //! }
|
| 102 | //!
|
| 103 | //! impl ops::Add<&Val> for Val {
|
| 104 | //! type Output = Val;
|
| 105 | //! fn add(self, b: &Val) -> Self::Output {
|
| 106 | //! let a = self;
|
| 107 | //! Val { v: a.v + b.v }
|
| 108 | //! }
|
| 109 | //! }
|
| 110 | //!
|
| 111 | //! impl ops::Add<Val> for &Val {
|
| 112 | //! type Output = Val;
|
| 113 | //! fn add(self, b: Val) -> Self::Output {
|
| 114 | //! let a = self;
|
| 115 | //! Val { v: a.v + b.v }
|
| 116 | //! }
|
| 117 | //! }
|
| 118 | //!
|
| 119 | //! impl ops::Add<&Val> for &Val {
|
| 120 | //! type Output = Val;
|
| 121 | //! fn add(self, b: &Val) -> Self::Output {
|
| 122 | //! let a = self;
|
| 123 | //! Val { v: a.v + b.v }
|
| 124 | //! }
|
| 125 | //! }
|
| 126 | //! ```
|
| 127 | //! We are now able to add `Val`s and `&Val`s in any combination:
|
| 128 | //! ```
|
| 129 | //! # extern crate overload;
|
| 130 | //! # use overload::overload;
|
| 131 | //! # use std::ops;
|
| 132 | //! # #[derive(PartialEq, Debug)]
|
| 133 | //! # struct Val {
|
| 134 | //! # v: i32
|
| 135 | //! # }
|
| 136 | //! # overload!((a: ?Val) + (b: ?Val) -> Val { Val { v: a.v + b.v } });
|
| 137 | //! assert_eq!(Val{v:3} + Val{v:5}, Val{v:8});
|
| 138 | //! assert_eq!(Val{v:3} + &Val{v:5}, Val{v:8});
|
| 139 | //! assert_eq!(&Val{v:3} + Val{v:5}, Val{v:8});
|
| 140 | //! assert_eq!(&Val{v:3} + &Val{v:5}, Val{v:8});
|
| 141 | //! ```
|
| 142 | //!
|
| 143 | //! # Binary operators
|
| 144 | //!
|
| 145 | //! The general syntax to overload a binary operator between types `<a_type>` and `<b_type>` is:
|
| 146 | //! ```ignore
|
| 147 | //! overload!((<a_ident>: <a_type>) <op> (<b_ident>: <b_type>) -> <out_type> { /*body*/ });
|
| 148 | //! ```
|
| 149 | //! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation.
|
| 150 | //!
|
| 151 | //! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
|
| 152 | //!
|
| 153 | //! | Operator | Example | Trait |
|
| 154 | //! |----------|-----------------------------------------------------------------|--------|
|
| 155 | //! | + | `overload!((a: A) + (b: B) -> C { /*...*/ );` | Add |
|
| 156 | //! | - | `overload!((a: A) - (b: B) -> C { /*...*/ );` | Sub |
|
| 157 | //! | * | `overload!((a: A) * (b: B) -> C { /*...*/ );` | Mul |
|
| 158 | //! | / | `overload!((a: A) / (b: B) -> C { /*...*/ );` | Div |
|
| 159 | //! | % | `overload!((a: A) % (b: B) -> C { /*...*/ );` | Rem |
|
| 160 | //! | & | `overload!((a: A) & (b: B) -> C { /*...*/ );` | BitAnd |
|
| 161 | //! | \| | <code>overload!((a: A) | (b: B) -> C { /\*...*\/ );</code> | BitOr |
|
| 162 | //! | ^ | `overload!((a: A) ^ (b: B) -> C { /*...*/ );` | BitXor |
|
| 163 | //! | << | `overload!((a: A) << (b: B) -> C { /*...*/ );` | Shl |
|
| 164 | //! | >> | `overload!((a: A) >> (b: B) -> C { /*...*/ );` | Shr |
|
| 165 | //!
|
| 166 | //! # Assignment operators
|
| 167 | //!
|
| 168 | //! The general syntax to overload an assignment operator between types `<a_type>` and `<b_type>` is:
|
| 169 | //! ```ignore
|
| 170 | //! overload!((<a_ident>: &mut <a_type>) <op> (<b_ident>: <b_type>) { /*body*/ });
|
| 171 | //! ```
|
| 172 | //! Inside the body you can use `<a_ident>` and `<b_ident>` freely to perform any computation and mutate `<a_ident>` as desired.
|
| 173 | //!
|
| 174 | //! | Operator | Example | Trait |
|
| 175 | //! |----------|------------------------------------------------------------------|--------------|
|
| 176 | //! | += | `overload!((a: &mut A) += (b: B) { /*...*/ );` | AddAssign |
|
| 177 | //! | -= | `overload!((a: &mut A) -= (b: B) { /*...*/ );` | SubAssign |
|
| 178 | //! | *= | `overload!((a: &mut A) *= (b: B) { /*...*/ );` | MulAssign |
|
| 179 | //! | /= | `overload!((a: &mut A) /= (b: B) { /*...*/ );` | DivAssign |
|
| 180 | //! | %= | `overload!((a: &mut A) %= (b: B) { /*...*/ );` | RemAssign |
|
| 181 | //! | &= | `overload!((a: &mut A) &= (b: B) { /*...*/ );` | BitAndAssign |
|
| 182 | //! | \|= | <code>overload!((a: &mut A) |= (b: B) { /\*...*\/ );</code> | BitOrAssign |
|
| 183 | //! | ^= | `overload!((a: &mut A) ^= (b: B) { /*...*/ );` | BitXorAssign |
|
| 184 | //! | <<= | `overload!((a: &mut A) <<= (b: B) { /*...*/ );` | ShlAssign |
|
| 185 | //! | >>= | `overload!((a: &mut A) >>= (b: B) { /*...*/ );` | ShrAssign |
|
| 186 | //!
|
| 187 | //! # Unary operators
|
| 188 | //!
|
| 189 | //! The general syntax to overload a unary operator for type `<a_type>` is:
|
| 190 | //! ```ignore
|
| 191 | //! overload!(<op> (<a_ident>: <a_type>) -> <out_type> { /*body*/ });
|
| 192 | //! ```
|
| 193 | //! Inside the body you can use `<a_ident>` freely to perform any computation.
|
| 194 | //!
|
| 195 | //! The last line of the body needs to be an expression (i.e. no `;` at the end of the line) of type `<out_type>`.
|
| 196 | //!
|
| 197 | //! | Operator | Example | Trait |
|
| 198 | //! |----------|---------------------------------------------------------|-------|
|
| 199 | //! | - | `overload!(- (a: A) -> B { /*...*/ );` | Neg |
|
| 200 | //! | ! | `overload!(! (a: A) -> B { /*...*/ );` | Not |
|
| 201 | //!
|
| 202 | //! # Notes
|
| 203 | //!
|
| 204 | //! Remember that you can only overload operators between one or more types if at least one of the types is defined in the current crate.
|
| 205 |
|
| 206 | #[macro_use ]
|
| 207 | mod unary;
|
| 208 |
|
| 209 | #[macro_use ]
|
| 210 | mod assignment;
|
| 211 |
|
| 212 | #[macro_use ]
|
| 213 | mod binary;
|
| 214 |
|
| 215 | /// Overloads an operator. See the [module level documentation](index.html) for more information.
|
| 216 | #[macro_export (local_inner_macros)]
|
| 217 | macro_rules! overload {
|
| 218 | // Unary (both owned and borrowed)
|
| 219 | ($op:tt ($i:ident : ? $t:ty) -> $out:ty $body:block) => (
|
| 220 | _overload_unary!($op, $i, $t, $out, $body);
|
| 221 | _overload_unary!($op, $i, &$t, $out, $body);
|
| 222 | );
|
| 223 | // Unary (either owned or borrowed)
|
| 224 | ($op:tt ($i:ident : $t:ty) -> $out:ty $body:block) => (
|
| 225 | _overload_unary!($op, $i, $t, $out, $body);
|
| 226 | );
|
| 227 | // Assignment (both owned and borrowed)
|
| 228 | (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : ? $rt:ty) $body:block) => (
|
| 229 | _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
|
| 230 | _overload_assignment!($op, $li, $lt, $ri, &$rt, $body);
|
| 231 | );
|
| 232 | // Assignment (either owned or borrowed)
|
| 233 | (($li:ident : &mut $lt:ty) $op:tt ($ri:ident : $rt:ty) $body:block) => (
|
| 234 | _overload_assignment!($op, $li, $lt, $ri, $rt, $body);
|
| 235 | );
|
| 236 | // Binary (both - both)
|
| 237 | (($li:ident : ? $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
|
| 238 | _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
|
| 239 | _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
|
| 240 | _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
|
| 241 | _overload_binary!($op, $li, &$lt, $ri, &$rt, $out, $body);
|
| 242 | );
|
| 243 | // Binary (both - either)
|
| 244 | (($li:ident : ? $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
|
| 245 | _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
|
| 246 | _overload_binary!($op, $li, &$lt, $ri, $rt, $out, $body);
|
| 247 | );
|
| 248 | // Binary (either - both)
|
| 249 | (($li:ident : $lt:ty) $op:tt ($ri:ident : ? $rt:ty) -> $out:ty $body:block) => (
|
| 250 | _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
|
| 251 | _overload_binary!($op, $li, $lt, $ri, &$rt, $out, $body);
|
| 252 | );
|
| 253 | // Binary (either - either)
|
| 254 | (($li:ident : $lt:ty) $op:tt ($ri:ident : $rt:ty) -> $out:ty $body:block) => (
|
| 255 | _overload_binary!($op, $li, $lt, $ri, $rt, $out, $body);
|
| 256 | );
|
| 257 | }
|
| 258 | |