この記事は Rustその2 Advent Calendar 2018 の15日目の記事です。
記事を書くときに使用しているRustのバージョンは1.31.0です。
const fn
とは
Rust 2018から使えるようになった定数を返す関数。
実行時に呼び出すこともできるなどC++のconstexprに似ている。
コンパイル時呼び出し
const fn const_fn() -> i32 {
0
}
fn main() {
const V: i32 = const_fn(); // 定数を返す
assert_eq!(V, 0);
}
実行時呼び出し
const fn const_fn() -> i32 {
0
}
fn main() {
let v: i32 = const_fn();
assert_eq!(v, 0);
}
引数
引数を受け取る事もできる。
const fn const_fn(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
const V: i32 = const_fn(1, 2);
assert_eq!(V, 3);
}
引数は参照で受け取ることもできるがmut
で受け取ることはできない。
ライフタイムを指定することはできる。
制限
追記: 2020/08/29
1.46.0時点でかなりの制限がなくなったためこの項目の内容は「過去のバージョンは制限が多くて大変だったんだな」くらいの気持ちで読んでください。
関数内でif
などを使おうとすると下記のようなエラーが出る。
error: `if`, `match`, `&&` and `||` are not stable in const fn
つまりif
もmatch
も&&
も||
も使えないので。
const fn is_even(v: i32) -> bool {
v != 0 && v % 2 == 0
}
こんな関数もコンパイルエラーになる。
ただし&
は使えるので下記は問題ない。
const fn is_even(v: i32) -> bool {
(v != 0) & (v % 2 == 0)
}
エラーメッセージには表示されていなかったがloop
もwhile
も使えない。
関数内で定数は定義できるが変数は定義できない。
const fn const_fn() {
const V: i32 = 0; // OK
let v: i32 = 0; // Error
}
変数が使えないのでfor
も使えない。
関数の引数を&mut
することもできない。
使えないもの
if
match
loop
- 変数
-
for
(変数が使えないので) &&
||
- 関数の引数を
&mut
にする - 関数内部で
const fn
ではない関数を呼び出す - 関数ポインタ
感想
使い所がかなり限られる。
というか自分は使うことがなさそう。
使い所があれば誰か教えてください。
C++11のconstexprは条件演算子とかオーバーロードとかで多少複雑な処理ができたがRustだとそれもできない。
わかったことが増えたら追加すると思います。
追加
##abs
の実装はできた。
Rustのconst fnでabs
1.33.0で一部の制限が緩和された
Rustのconst fnの制限が緩和された(Rust 1.33.0)