Overloadable operators.
Implementing these traits allows you to overload certain operators.
Some of these traits are imported by the prelude, so they are available in every Rust program. Only operators backed by traits can be overloaded. For example, the addition operator (+
) can be overloaded through the Add
trait, but since the assignment operator (=
) has no backing trait, there is no way of overloading its semantics. Additionally, this module does not provide any mechanism to create new operators. If traitless overloading or custom operators are required, you should look toward macros or compiler plugins to extend Rust's syntax.
Note that the &&
and ||
operators short-circuit, i.e. they only evaluate their second operand if it contributes to the result. Since this behavior is not enforceable by traits, &&
and ||
are not supported as overloadable operators.
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.
This example creates a Point
struct that implements Add
and Sub
, and then demonstrates adding and subtracting two Point
s.
use std::ops::{Add, Sub}; #[derive(Debug)] struct Point { x: i32, y: i32, } impl Add for Point { type Output = Point; fn add(self, other: Point) -> Point { Point {x: self.x + other.x, y: self.y + other.y} } } impl Sub for Point { type Output = Point; fn sub(self, other: Point) -> Point { Point {x: self.x - other.x, y: self.y - other.y} } } fn main() { println!("{:?}", Point {x: 1, y: 0} + Point {x: 2, y: 3}); println!("{:?}", Point {x: 1, y: 0} - Point {x: 2, y: 3}); }
See the documentation for each trait for an example implementation.
The Fn
, FnMut
, and FnOnce
traits are implemented by types that can be invoked like functions. Note that Fn
takes &self
, FnMut
takes &mut self
and FnOnce
takes self
. These correspond to the three kinds of methods that can be invoked on an instance: call-by-reference, call-by-mutable-reference, and call-by-value. The most common use of these traits is to act as bounds to higher-level functions that take functions or closures as arguments.
Taking a Fn
as a parameter:
fn call_with_one<F>(func: F) -> usize where F: Fn(usize) -> usize { func(1) } let double = |x| x * 2; assert_eq!(call_with_one(double), 2);
Taking a FnMut
as a parameter:
fn do_twice<F>(mut func: F) where F: FnMut() { func(); func(); } let mut x: usize = 1; { let add_two_to_x = || x += 2; do_twice(add_two_to_x); } assert_eq!(x, 5);
Taking a FnOnce
as a parameter:
fn consume_with_relish<F>(func: F) where F: FnOnce() -> String { // `func` consumes its captured variables, so it cannot be run more // than once println!("Consumed: {}", func()); println!("Delicious!"); // Attempting to invoke `func()` again will throw a `use of moved // value` error for `func` } let x = String::from("x"); let consume_and_return_x = move || x; consume_with_relish(consume_and_return_x); // `consume_and_return_x` can no longer be invoked at this point
Range | A (half-open) range which is bounded at both ends: { x | start <= x < end }. Use |
RangeFrom | A range which is only bounded below: { x | start <= x }. Use |
RangeFull | An unbounded range. Use |
RangeTo | A range which is only bounded above: { x | x < end }. Use |
RangeToInclusive | [ Experimental ] An inclusive range which is only bounded above: { x | x <= end }. Use |
RangeInclusive | [ Experimental ] An inclusive range which is bounded at both ends: { x | start <= x <= end }. Use |
Add | The |
AddAssign | The |
BitAnd | The |
BitAndAssign | The |
BitOr | The |
BitOrAssign | The |
BitXor | The |
BitXorAssign | The |
Deref | The |
DerefMut | The |
Div | The |
DivAssign | The |
Drop | The |
Fn | A version of the call operator that takes an immutable receiver. |
FnMut | A version of the call operator that takes a mutable receiver. |
FnOnce | A version of the call operator that takes a by-value receiver. |
Index | The |
IndexMut | The |
Mul | The |
MulAssign | The |
Neg | The |
Not | The |
Rem | The |
RemAssign | The |
Shl | The |
ShlAssign | The |
Shr | The |
ShrAssign | The |
Sub | The |
SubAssign | The |
BoxPlace | [ Experimental ] Specialization of |
Boxed | [ Experimental ] Core trait for the |
Carrier | [ Experimental ] A trait for types which have success and error states and are meant to work with the question mark operator. When the |
CoerceUnsized | [ Experimental ] Trait that indicates that this is a pointer or a wrapper for one, where unsizing can be performed on the pointee. |
InPlace | [ Experimental ] Specialization of |
Place | [ Experimental ] Both |
Placer | [ Experimental ] Interface to implementations of |
© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/std/ops/index.html