13
13
//! Implementing these traits allows you to get an effect similar to
14
14
//! overloading operators.
15
15
//!
16
- //! The values for the right hand side of an operator are automatically
17
- //! borrowed, so `a + b` is sugar for `a.add(&b)`.
18
- //!
19
- //! All of these traits are imported by the prelude, so they are available in
16
+ //! Some of these traits are imported by the prelude, so they are available in
20
17
//! every Rust program.
21
18
//!
19
+ //! Many of the operators take their operands by value. In non-generic
20
+ //! contexts involving built-in types, this is usually not a problem.
21
+ //! However, using these operators in generic code, requires some
22
+ //! attention if values have to be reused as opposed to letting the operators
23
+ //! consume them. One option is to occasionally use `clone()`.
24
+ //! Another option is to rely on the types involved providing additional
25
+ //! operator implementations for references. For example, for a user-defined
26
+ //! type `T` which is supposed to support addition, it is probably a good
27
+ //! idea to have both `T` and `&T` implement the traits `Add<T>` and `Add<&T>`
28
+ //! so that generic code can be written without unnecessary cloning.
29
+ //!
22
30
//! # Example
23
31
//!
24
32
//! This example creates a `Point` struct that implements `Add` and `Sub`, and then
@@ -96,6 +104,58 @@ pub trait Drop {
96
104
fn drop ( & mut self ) ;
97
105
}
98
106
107
+ // implements the unary operator "op &T"
108
+ // based on "op T" where T is expected to be `Copy`able
109
+ macro_rules! forward_ref_unop {
110
+ ( impl $imp: ident, $method: ident for $t: ty) => {
111
+ #[ unstable = "recently added, waiting for dust to settle" ]
112
+ impl <' a> $imp for & ' a $t {
113
+ type Output = <$t as $imp>:: Output ;
114
+
115
+ #[ inline]
116
+ fn $method( self ) -> <$t as $imp>:: Output {
117
+ $imp:: $method( * self )
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ // implements binary operators "&T op U", "T op &U", "&T op &U"
124
+ // based on "T op U" where T and U are expected to be `Copy`able
125
+ macro_rules! forward_ref_binop {
126
+ ( impl $imp: ident, $method: ident for $t: ty, $u: ty) => {
127
+ #[ unstable = "recently added, waiting for dust to settle" ]
128
+ impl <' a> $imp<$u> for & ' a $t {
129
+ type Output = <$t as $imp<$u>>:: Output ;
130
+
131
+ #[ inline]
132
+ fn $method( self , other: $u) -> <$t as $imp<$u>>:: Output {
133
+ $imp:: $method( * self , other)
134
+ }
135
+ }
136
+
137
+ #[ unstable = "recently added, waiting for dust to settle" ]
138
+ impl <' a> $imp<& ' a $u> for $t {
139
+ type Output = <$t as $imp<$u>>:: Output ;
140
+
141
+ #[ inline]
142
+ fn $method( self , other: & ' a $u) -> <$t as $imp<$u>>:: Output {
143
+ $imp:: $method( self , * other)
144
+ }
145
+ }
146
+
147
+ #[ unstable = "recently added, waiting for dust to settle" ]
148
+ impl <' a, ' b> $imp<& ' a $u> for & ' b $t {
149
+ type Output = <$t as $imp<$u>>:: Output ;
150
+
151
+ #[ inline]
152
+ fn $method( self , other: & ' a $u) -> <$t as $imp<$u>>:: Output {
153
+ $imp:: $method( * self , * other)
154
+ }
155
+ }
156
+ }
157
+ }
158
+
99
159
/// The `Add` trait is used to specify the functionality of `+`.
100
160
///
101
161
/// # Example
@@ -144,6 +204,8 @@ macro_rules! add_impl {
144
204
#[ inline]
145
205
fn add( self , other: $t) -> $t { self + other }
146
206
}
207
+
208
+ forward_ref_binop! { impl Add , add for $t, $t }
147
209
) * )
148
210
}
149
211
@@ -197,6 +259,8 @@ macro_rules! sub_impl {
197
259
#[ inline]
198
260
fn sub( self , other: $t) -> $t { self - other }
199
261
}
262
+
263
+ forward_ref_binop! { impl Sub , sub for $t, $t }
200
264
) * )
201
265
}
202
266
@@ -250,6 +314,8 @@ macro_rules! mul_impl {
250
314
#[ inline]
251
315
fn mul( self , other: $t) -> $t { self * other }
252
316
}
317
+
318
+ forward_ref_binop! { impl Mul , mul for $t, $t }
253
319
) * )
254
320
}
255
321
@@ -303,6 +369,8 @@ macro_rules! div_impl {
303
369
#[ inline]
304
370
fn div( self , other: $t) -> $t { self / other }
305
371
}
372
+
373
+ forward_ref_binop! { impl Div , div for $t, $t }
306
374
) * )
307
375
}
308
376
@@ -356,6 +424,8 @@ macro_rules! rem_impl {
356
424
#[ inline]
357
425
fn rem( self , other: $t) -> $t { self % other }
358
426
}
427
+
428
+ forward_ref_binop! { impl Rem , rem for $t, $t }
359
429
) * )
360
430
}
361
431
@@ -371,6 +441,8 @@ macro_rules! rem_float_impl {
371
441
unsafe { $fmod( self , other) }
372
442
}
373
443
}
444
+
445
+ forward_ref_binop! { impl Rem , rem for $t, $t }
374
446
}
375
447
}
376
448
@@ -429,6 +501,8 @@ macro_rules! neg_impl {
429
501
#[ stable]
430
502
fn neg( self ) -> $t { -self }
431
503
}
504
+
505
+ forward_ref_unop! { impl Neg , neg for $t }
432
506
) * )
433
507
}
434
508
@@ -441,6 +515,8 @@ macro_rules! neg_uint_impl {
441
515
#[ inline]
442
516
fn neg( self ) -> $t { -( self as $t_signed) as $t }
443
517
}
518
+
519
+ forward_ref_unop! { impl Neg , neg for $t }
444
520
}
445
521
}
446
522
@@ -502,6 +578,8 @@ macro_rules! not_impl {
502
578
#[ inline]
503
579
fn not( self ) -> $t { !self }
504
580
}
581
+
582
+ forward_ref_unop! { impl Not , not for $t }
505
583
) * )
506
584
}
507
585
@@ -555,6 +633,8 @@ macro_rules! bitand_impl {
555
633
#[ inline]
556
634
fn bitand( self , rhs: $t) -> $t { self & rhs }
557
635
}
636
+
637
+ forward_ref_binop! { impl BitAnd , bitand for $t, $t }
558
638
) * )
559
639
}
560
640
@@ -608,6 +688,8 @@ macro_rules! bitor_impl {
608
688
#[ inline]
609
689
fn bitor( self , rhs: $t) -> $t { self | rhs }
610
690
}
691
+
692
+ forward_ref_binop! { impl BitOr , bitor for $t, $t }
611
693
) * )
612
694
}
613
695
@@ -661,6 +743,8 @@ macro_rules! bitxor_impl {
661
743
#[ inline]
662
744
fn bitxor( self , other: $t) -> $t { self ^ other }
663
745
}
746
+
747
+ forward_ref_binop! { impl BitXor , bitxor for $t, $t }
664
748
) * )
665
749
}
666
750
@@ -716,6 +800,8 @@ macro_rules! shl_impl {
716
800
self << other
717
801
}
718
802
}
803
+
804
+ forward_ref_binop! { impl Shl , shl for $t, $f }
719
805
)
720
806
}
721
807
@@ -786,6 +872,8 @@ macro_rules! shr_impl {
786
872
self >> other
787
873
}
788
874
}
875
+
876
+ forward_ref_binop! { impl Shr , shr for $t, $f }
789
877
)
790
878
}
791
879
0 commit comments