【Nigtly Rust】コンパイル時と実行時で処理を呼び分けるconst_eval_select
| 2026/04/21 01:59 | 公開 |
この記事は2026-04-19のnightlyビルドで動作の確認をしています
const_eval_selectとは
コンテキスト(constコンテキストかどうか)によって呼び出す関数を切り替えられるようにするための機能です。
std::intrinsics::const_eval_select
使い方
const_eval_select(関数に渡す引数, コンパイル時に呼び出す関数, 実行時に呼び出す関数) のように使用します。
const_eval_select(args, const_fn, runtime_fn)のようにすることで、
コンパイル時には const_fn(args)、実行時には const_fn(args)に置き換えられます。
第一引数に渡すのは第二、第三引数に渡す関数の呼び出しに使用する引数のタプルです。
例
平方根を求める関数(sqrt)をコンパイル時にも使えるようにするための例です。
実行時にはf64のsqrtを呼び出しますが、コンパイル時にはニュートン法を用いて平方根を求める関数を呼び出すようにしています。
#![feature(core_intrinsics)]
#![feature(const_eval_select)]
use std::intrinsics::const_eval_select;
// コンパイル時に呼び出される関数
const fn ct_sqrt_f64(x: f64) -> f64 {
if x < 0.0 {
return f64::NAN;
}
if x == 0.0 {
return 0.0;
}
let mut guess = x / 2.0;
loop {
let new_guess = 0.5 * (guess + (x / guess));
if (guess - new_guess).abs() < 1e-10 {
break new_guess;
}
guess = new_guess;
}
}
// 実行時に呼び出される関数
fn rt_sqrt_f64(x: f64) -> f64 {
x.sqrt() // f64のsqrtを呼ぶ
}
// 呼び分けを行うラッパー関数
pub const fn sqrt(x: f64) -> f64 {
// 引数のタプル, コンパイル時関数, 実行時関数を渡す
const_eval_select((x,), ct_sqrt_f64, rt_sqrt_f64)
}
呼び出し側は通常の関数呼び出しのように使うことができます。
fn main() {
const COMPILE_TIME_RESULT: f64 = sqrt(2.0);
println!("Compile-time sqrt(2.0) = {}", COMPILE_TIME_RESULT);
let runtime_result = sqrt(2.0);
println!("Runtime sqrt(2.0) = {}", runtime_result);
}
注意点
const_eval_selectに渡す2つの関数は、同じ引数を取り同じ型の値を返す必要があります。
またcore_intrinsicsを有効にすることで以下の警告が出ます。
warning: the feature `core_intrinsics` is internal to the compiler or standard library
--> src/main.rs:1:12
|
1 | #![feature(core_intrinsics)]
| ^^^^^^^^^^^^^^^
|
= note: using it is strongly discouraged
= note: `#[warn(internal_features)]` on by default
「core_intrinsicsはコンパイラもしくは標準ライブラリの内部機能です」という警告で、おそらくユーザー側で使用することは推奨されていないです。
どうしても使用したい場合は警告を抑制して使用することになると思います。
まとめ
const_eval_selectを使用することでコンパイル時に呼ぶ関数と実行時に呼ぶ関数を切り替えることができるconst_eval_selectには引数のタプル、コンパイル時に呼び出す関数、実行時に呼び出す関数を渡す- 使用するために
core_intrinsicsを有効にすると警告が出る