1313//! Implementing these traits allows you to get an effect similar to
1414//! overloading operators.
1515//!
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
2017//! every Rust program.
2118//!
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+ //!
2230//! # Example
2331//!
2432//! This example creates a `Point` struct that implements `Add` and `Sub`, and then
@@ -96,6 +104,58 @@ pub trait Drop {
96104 fn drop ( & mut self ) ;
97105}
98106
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+
99159/// The `Add` trait is used to specify the functionality of `+`.
100160///
101161/// # Example
@@ -144,6 +204,8 @@ macro_rules! add_impl {
144204 #[ inline]
145205 fn add( self , other: $t) -> $t { self + other }
146206 }
207+
208+ forward_ref_binop! { impl Add , add for $t, $t }
147209 ) * )
148210}
149211
@@ -197,6 +259,8 @@ macro_rules! sub_impl {
197259 #[ inline]
198260 fn sub( self , other: $t) -> $t { self - other }
199261 }
262+
263+ forward_ref_binop! { impl Sub , sub for $t, $t }
200264 ) * )
201265}
202266
@@ -250,6 +314,8 @@ macro_rules! mul_impl {
250314 #[ inline]
251315 fn mul( self , other: $t) -> $t { self * other }
252316 }
317+
318+ forward_ref_binop! { impl Mul , mul for $t, $t }
253319 ) * )
254320}
255321
@@ -303,6 +369,8 @@ macro_rules! div_impl {
303369 #[ inline]
304370 fn div( self , other: $t) -> $t { self / other }
305371 }
372+
373+ forward_ref_binop! { impl Div , div for $t, $t }
306374 ) * )
307375}
308376
@@ -356,6 +424,8 @@ macro_rules! rem_impl {
356424 #[ inline]
357425 fn rem( self , other: $t) -> $t { self % other }
358426 }
427+
428+ forward_ref_binop! { impl Rem , rem for $t, $t }
359429 ) * )
360430}
361431
@@ -371,6 +441,8 @@ macro_rules! rem_float_impl {
371441 unsafe { $fmod( self , other) }
372442 }
373443 }
444+
445+ forward_ref_binop! { impl Rem , rem for $t, $t }
374446 }
375447}
376448
@@ -429,6 +501,8 @@ macro_rules! neg_impl {
429501 #[ stable]
430502 fn neg( self ) -> $t { -self }
431503 }
504+
505+ forward_ref_unop! { impl Neg , neg for $t }
432506 ) * )
433507}
434508
@@ -441,6 +515,8 @@ macro_rules! neg_uint_impl {
441515 #[ inline]
442516 fn neg( self ) -> $t { -( self as $t_signed) as $t }
443517 }
518+
519+ forward_ref_unop! { impl Neg , neg for $t }
444520 }
445521}
446522
@@ -502,6 +578,8 @@ macro_rules! not_impl {
502578 #[ inline]
503579 fn not( self ) -> $t { !self }
504580 }
581+
582+ forward_ref_unop! { impl Not , not for $t }
505583 ) * )
506584}
507585
@@ -555,6 +633,8 @@ macro_rules! bitand_impl {
555633 #[ inline]
556634 fn bitand( self , rhs: $t) -> $t { self & rhs }
557635 }
636+
637+ forward_ref_binop! { impl BitAnd , bitand for $t, $t }
558638 ) * )
559639}
560640
@@ -608,6 +688,8 @@ macro_rules! bitor_impl {
608688 #[ inline]
609689 fn bitor( self , rhs: $t) -> $t { self | rhs }
610690 }
691+
692+ forward_ref_binop! { impl BitOr , bitor for $t, $t }
611693 ) * )
612694}
613695
@@ -661,6 +743,8 @@ macro_rules! bitxor_impl {
661743 #[ inline]
662744 fn bitxor( self , other: $t) -> $t { self ^ other }
663745 }
746+
747+ forward_ref_binop! { impl BitXor , bitxor for $t, $t }
664748 ) * )
665749}
666750
@@ -716,6 +800,8 @@ macro_rules! shl_impl {
716800 self << other
717801 }
718802 }
803+
804+ forward_ref_binop! { impl Shl , shl for $t, $f }
719805 )
720806}
721807
@@ -786,6 +872,8 @@ macro_rules! shr_impl {
786872 self >> other
787873 }
788874 }
875+
876+ forward_ref_binop! { impl Shr , shr for $t, $f }
789877 )
790878}
791879
0 commit comments