42
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rust 2Advent Calendar 2020

Day 22

Rustのジェネリクスパラメーターに定数を渡せるようになる(const generics)

Last updated at Posted at 2020-12-22

この記事はRust 2 Advent Calendar 2020 22日目の記事です。

const genericsとは

const genericsとは下記のようなジェネリクスパラメーターに定数を渡せる機能です。

struct Foo<const N: usize> {}
let v = Foo::<5> {};

記事を書いている2020/12/22時点ではstableに入っていませんが、こちらのissueによるとRust 1.50でstableに入れることを予定しているそうです。
C++でテンプレートメタプログラミングをしていた方々には慣れ親しんだ機能だと思います。

const genericsを利用する方法

const genericsを利用するにはnightlyチャンネルで#![feature(min_const_generics)]を書く必要があります

使用可能な箇所

基本的にジェネリクスを使用できる場所でならどこでも使用できます。

struct A<const N: i32>;
trait B<const N: i32> {}
fn function<const N: i32>() {}
enum E<const N: i32> {}

特定のパラメーターのものに対してtraitを実装することもできます。

struct A<const N: i32>;

trait Hoge {
    fn hoge();
}

// Nが0のときのみHogeを実装
impl Hoge for A<0> {
    fn hoge() {}
}

fn main() {
    A::<0>::hoge(); // OK
    A::<1>::hoge(); // コンパイルエラー
}

配列の長さに関わらず特定のtraitを実装することもできます。

trait Hoge {
    fn hoge(&self) { }
}

impl<T, const N: usize> Hoge for [T; N] {
    fn hoge(&self) { }
}

パラメーターの制限

定数の型は整数型もしくはbool, charだけが許可されます。
具体的にはu8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize, char, boolだけが許可されます。

struct A<const N: f32>;

のようにf32などを使用しようとするとコンパイルエラーが発生します。

error: `f32` is forbidden as the type of a const generic parameter
 --> src/lib.rs:3:19
  |
3 | struct A<const N: f32>;
  |                   ^^^
  |
  = note: the only supported types are integers, `bool` and `char`
  = help: more complex types are supported with `#[feature(const_generics)]`

計算結果やconst fnの戻り値を渡すことができますが、{}で囲んでやる必要があります。

struct A<const N: i32>;

const fn function() -> i32 {
    42
}

fn main() {
    let _ = A::<{1 + 2}>{};      // OK
    let _ = A::<1 + 2>{};        // コンパイルエラー
    let _ = A::<{function()}>{}; // OK
    let _ = A::<function()>{};   // コンパイルエラー
}

下記のように定数の型をジェネリクスで指定することはできません。

struct A<T, const N: T>;

近い将来に実装される可能性も低いそうです。


順番にも制限があり、定数は型パラメーターよりも後に来る必要があります。

struct A<T, const N: i32>; // 型が先なのでOK
struct B<const N: i32, T>; // 型が後なのでコンパイルエラー

あとがき

const genericsが使えるようになればジェネリックパラメーターに定数を渡せるようになります。
現状の予定では制限が多いですが便利な機能なのでstable入りが非常に楽しみです。

自分で使うことが少なくてもいろんなcrateがこの機能によって使いやすくなったり便利になったりするんじゃないかと思っています。

今回書いた内容は冒頭にもリンクを張ったこちらのissueを参考にしています。
興味がある方はissueの方も覗いてみてください。

42
16
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
42
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?