//! Implementing these traits allows you to get an effect similar to
//! overloading operators.
//!
-//! The values for the right hand side of an operator are automatically
-//! borrowed, so `a + b` is sugar for `a.add(&b)`.
-//!
-//! All of these traits are imported by the prelude, so they are available in
+//! Some of these traits are imported by the prelude, so they are available in
//! every Rust program.
//!
+//! Many of the operators take their operands by value. In non-generic
+//! contexts involving built-in types, this is usually not a problem.
+//! However, using these operators in generic code, requires some
+//! attention if values have to be reused as opposed to letting the operators
+//! consume them. One option is to occasionally use `clone()`.
+//! Another option is to rely on the types involved providing additional
+//! operator implementations for references. For example, for a user-defined
+//! type `T` which is supposed to support addition, it is probably a good
+//! idea to have both `T` and `&T` implement the traits `Add<T>` and `Add<&T>`
+//! so that generic code can be written without unnecessary cloning.
+//!
//! # Example
//!
//! This example creates a `Point` struct that implements `Add` and `Sub`, and then
//! demonstrates adding and subtracting two `Point`s.
//!
//! ```rust
-//! #![feature(associated_types)]
-//!
//! use std::ops::{Add, Sub};
//!
//! #[derive(Show)]
fn drop(&mut self);
}
+// implements the unary operator "op &T"
+// based on "op T" where T is expected to be `Copy`able
+macro_rules! forward_ref_unop {
+ (impl $imp:ident, $method:ident for $t:ty) => {
+ #[unstable = "recently added, waiting for dust to settle"]
+ impl<'a> $imp for &'a $t {
+ type Output = <$t as $imp>::Output;
+
+ #[inline]
+ fn $method(self) -> <$t as $imp>::Output {
+ $imp::$method(*self)
+ }
+ }
+ }
+}
+
+// implements binary operators "&T op U", "T op &U", "&T op &U"
+// based on "T op U" where T and U are expected to be `Copy`able
+macro_rules! forward_ref_binop {
+ (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
+ #[unstable = "recently added, waiting for dust to settle"]
+ impl<'a> $imp<$u> for &'a $t {
+ type Output = <$t as $imp<$u>>::Output;
+
+ #[inline]
+ fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
+ $imp::$method(*self, other)
+ }
+ }
+
+ #[unstable = "recently added, waiting for dust to settle"]
+ impl<'a> $imp<&'a $u> for $t {
+ type Output = <$t as $imp<$u>>::Output;
+
+ #[inline]
+ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
+ $imp::$method(self, *other)
+ }
+ }
+
+ #[unstable = "recently added, waiting for dust to settle"]
+ impl<'a, 'b> $imp<&'a $u> for &'b $t {
+ type Output = <$t as $imp<$u>>::Output;
+
+ #[inline]
+ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
+ $imp::$method(*self, *other)
+ }
+ }
+ }
+}
+
/// The `Add` trait is used to specify the functionality of `+`.
///
/// # Example
/// calling `add`, and therefore, `main` prints `Adding!`.
///
/// ```rust
-/// #![feature(associated_types)]
-///
/// use std::ops::Add;
///
/// #[derive(Copy)]
#[inline]
fn add(self, other: $t) -> $t { self + other }
}
+
+ forward_ref_binop! { impl Add, add for $t, $t }
)*)
}
/// calling `sub`, and therefore, `main` prints `Subtracting!`.
///
/// ```rust
-/// #![feature(associated_types)]
-///
/// use std::ops::Sub;
///
/// #[derive(Copy)]
#[inline]
fn sub(self, other: $t) -> $t { self - other }
}
+
+ forward_ref_binop! { impl Sub, sub for $t, $t }
)*)
}
/// calling `mul`, and therefore, `main` prints `Multiplying!`.
///
/// ```rust
-/// #![feature(associated_types)]
-///
/// use std::ops::Mul;
///
/// #[derive(Copy)]
#[inline]
fn mul(self, other: $t) -> $t { self * other }
}
+
+ forward_ref_binop! { impl Mul, mul for $t, $t }
)*)
}
/// calling `div`, and therefore, `main` prints `Dividing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Div;
///
/// #[derive(Copy)]
#[inline]
fn div(self, other: $t) -> $t { self / other }
}
+
+ forward_ref_binop! { impl Div, div for $t, $t }
)*)
}
/// calling `rem`, and therefore, `main` prints `Remainder-ing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Rem;
///
/// #[derive(Copy)]
#[inline]
fn rem(self, other: $t) -> $t { self % other }
}
+
+ forward_ref_binop! { impl Rem, rem for $t, $t }
)*)
}
unsafe { $fmod(self, other) }
}
}
+
+ forward_ref_binop! { impl Rem, rem for $t, $t }
}
}
/// `neg`, and therefore, `main` prints `Negating!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Neg;
///
/// struct Foo;
#[stable]
fn neg(self) -> $t { -self }
}
+
+ forward_ref_unop! { impl Neg, neg for $t }
)*)
}
#[inline]
fn neg(self) -> $t { -(self as $t_signed) as $t }
}
+
+ forward_ref_unop! { impl Neg, neg for $t }
}
}
/// `not`, and therefore, `main` prints `Not-ing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Not;
///
/// struct Foo;
#[inline]
fn not(self) -> $t { !self }
}
+
+ forward_ref_unop! { impl Not, not for $t }
)*)
}
/// calling `bitand`, and therefore, `main` prints `Bitwise And-ing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::BitAnd;
///
/// #[derive(Copy)]
#[inline]
fn bitand(self, rhs: $t) -> $t { self & rhs }
}
+
+ forward_ref_binop! { impl BitAnd, bitand for $t, $t }
)*)
}
/// calling `bitor`, and therefore, `main` prints `Bitwise Or-ing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::BitOr;
///
/// #[derive(Copy)]
#[inline]
fn bitor(self, rhs: $t) -> $t { self | rhs }
}
+
+ forward_ref_binop! { impl BitOr, bitor for $t, $t }
)*)
}
/// calling `bitxor`, and therefore, `main` prints `Bitwise Xor-ing!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::BitXor;
///
/// #[derive(Copy)]
#[inline]
fn bitxor(self, other: $t) -> $t { self ^ other }
}
+
+ forward_ref_binop! { impl BitXor, bitxor for $t, $t }
)*)
}
/// calling `shl`, and therefore, `main` prints `Shifting left!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Shl;
///
/// #[derive(Copy)]
self << other
}
}
+
+ forward_ref_binop! { impl Shl, shl for $t, $f }
)
}
/// calling `shr`, and therefore, `main` prints `Shifting right!`.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Shr;
///
/// #[derive(Copy)]
self >> other
}
}
+
+ forward_ref_binop! { impl Shr, shr for $t, $f }
)
}
/// struct.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
/// struct.
///
/// ```
-/// #![feature(associated_types)]
-///
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {