📚
Rustで使える演算子オーバーロード(C++との比較)
| 演算子 | C++ | Rust | Rustトレイト | 備考 |
|---|---|---|---|---|
+ |
○ | ○ | Add |
|
- |
○ | ○ | Sub |
|
* |
○ | ○ | Mul |
|
/ |
○ | ○ | Div |
|
% |
○ | ○ | Rem |
|
+= |
○ | ○ | AddAssign |
|
-= |
○ | ○ | SubAssign |
|
*= |
○ | ○ | MulAssign |
|
/= |
○ | ○ | DivAssign |
|
%= |
○ | ○ | RemAssign |
|
==/!=
|
○ | ○ | PartialEq |
!=は==で自動実装 |
<,>,<=,>= |
○ | ○ | PartialOrd |
すべてPartialOrdで自動実装 |
! |
○ | ○ | Not |
単項否定 |
~ |
○ | ✕ | ― | Rustでビット演算(NOT)は!を使用 |
& |
○ | ○ | BitAnd |
ビット演算(AND) |
| |
○ | ○ | BitOr |
ビット演算(OR) |
^ |
○ | ○ | BitXor |
ビット演算(XOR) |
&= |
○ | ○ | BitAndAssign |
|
=| |
○ | ○ | BitOrAssign |
|
^= |
○ | ○ | BitXorAssign |
|
<< |
○ | ○ | Shl |
シフト |
>> |
○ | ○ | Shr |
|
<<= |
○ | ○ | ShlAssign |
|
>>= |
○ | ○ | ShrAssign |
|
[] |
○ | ○ |
Index, IndexMut
|
|
() |
○ | ○ |
Fn, FnMut, FnOnce
|
クロージャ呼び出し |
-> |
○ | ✕ | ― | Rustでは意味が異なるためオーバーロード不可 |
->* |
○ | ✕ | ― | |
=(代入) |
○ | ✕ | ― | Rustでは代入演算子自体のオーバーロード不可 |
++/-- |
○ | ✕ | ― | Rustは副作用排除のため非対応 |
,(カンマ) |
○ | ✕ | ― | Rustでは演算子として扱わない |
new/delete |
○ | ✕ | ― | Rustは所有権・安全性モデルが異なるため非対応 |
The Rust Programming Language 日本語版 付録B: 演算子と記号
Rust By Example 日本語版 演算子のオーバーロード
std::ops
書き方
pub struct StructName {
value: u32,
}
impl StructName {
// struct.add(other)という呼び方も残したいのでこの関数はそのまま
pub fn add(&self, other: Self) -> Self {
StructName {
value: self.value + other.value,
}
}
// 1回内部関数を噛ませることにより上のaddが呼べる(実質処理が無いのでinline)
#[inline]
fn add_internal(self, other: Self) -> Self {
self.add(other)
}
}
// 同じ型を対象にする場合は型指定なし。
impl std::ops::Add for StructName {
type Output = Self;
fn add(self, other: Self) -> Self {
self.add_internal(other) // add内で直接self.addを呼ぶと循環参照となる。
}
}
// 別の型を対象にしたい場合はAdd<T>とする。
impl std::ops::Add<u32> for StructName {
type Output = Self;
fn add(self, other: u32) -> Self {
StructName {
value: self.value + other,
}
}
}
// 逆順を定義したい場合はこんな感じ
impl std::ops::Add<StructName> for u32 {
type Output = StructName;
fn add(self, other: StructName) -> StructName {
StructName {
value: self + other.value,
}
}
}
add内での呼び出し関数がここでadd_internalとしたのは元々内部でadd関数を定義していたため、struct.add()という呼び出しを残すため、StructNameにadd(元々実装していた関数)を呼ぶためのadd_internalを追加した。
もちろんそのような柵がなければ演算子関数の中で直接計算してよい。
Discussion