この記事は 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)

1.46.0でさらに制限が緩和された

Rustのconst fnの制限がさらに緩和された(Rust 1.46.0)

广告
将在 10 秒后关闭
bannerAds