LoginSignup
10

More than 3 years have passed since last update.

Rustのconst fn

Last updated at Posted at 2018-12-15

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

つまりifmatch&&||も使えないので。

const fn is_even(v: i32) -> bool {
    v != 0 && v % 2 == 0
}

こんな関数もコンパイルエラーになる。
ただし&は使えるので下記は問題ない。

const fn is_even(v: i32) -> bool {
    (v != 0) & (v % 2 == 0)
}

エラーメッセージには表示されていなかったがloopwhileも使えない。
関数内で定数は定義できるが変数は定義できない。

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)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10