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 | |