可以使用类型关联的常量来推广函数的数组大小参数吗?

时间:2017-09-10 02:59:26

标签: types rust

Rust的类型系统并没有对大小进行概括,但是type associated constants(Rust 1.20中的新增内容)我认为通过声明一个恒定的大小可能有一些方法可以解决这个问题。在一个类型。

给定在Rust中对固定大小数组进行操作的函数,是否可能/实际使用类型常量来声明采用任意数组大小或至少预定义大小范围(1..32)的函数。

以小数学API为例:

// Cut down example of a math API

// Could be changed at compile time, otherwise quite limiting.
pub const DIMS: usize = 3;

pub fn sq(a: f64) -> f64 { a }

pub fn len_squared_vnvn(v0: &[f64; DIMS], v1: &[f64; DIMS]) -> f64 {
    let mut d = 0.0;
    for j in 0..DIMS {
        d += sq(v0[j] - v1[j]);
    }
    return d;
}

fn imul_vn_fl(v0: &mut [f64; DIMS], f: f64) {
    for j in 0..DIMS {
        v0[j] *= f;
    }
}

可以DIMS移动到与关联类型相关的常量,以便......

  • imul_vn_fl等函数可以与任意固定大小的数组一起使用。
  • 支持传递原始固定大小的数组类型,例如:[f64; SOME_CONSTANT_NUMBER]或更可能的是零成本转换为包装[f64; #]的类型并定义DIMS类型常量
  • 使用std::convert::From / Into,以避免在每次通话时显式写入演员表。
  • 生成的代码应该与使用常量大小一样高效(没有运行时大小检查)。

我想象这样的事情:

// this would be a macro to avoid re-writing for every size.
type f64v3 = u64;
impl VectorSize for f64v3 {
    const usize DIMS = 3;
}
// end macro

fn example() {
    let var: [f64; 3] = [0.0, 1.0, 2.0];
    imul_vn_fl(var, 0.5);

    // ...
}

1 个答案:

答案 0 :(得分:1)

相关常数的(当前?)限制是它们不能在泛型类型上调用。 即,按照您的示例,使用关联的常量,您可以执行此操作:

trait VectorSize {
    const DIMS: usize;
}

impl VectorSize for u64 {
    const DIMS: usize = 3usize;
}

fn imul_vn_fl(v0: &mut [f64; u64::DIMS], f: f64) {
    for j in 0..u64::DIMS {
        v0[j] *= f;
    }
}

但您最终希望能够使imul_vn_fl通用,并让它使用您的类型上定义的DIMS。这是关联常数仍然不足的地方(参见"缺点" https://github.com/rust-lang/rust/issues/29646中的第一个)

// this does not compile, unfortunately; T must be a concrete type
fn imul_vn_fl<T>(v0: &mut [f64; T::DIMS], f: f64) 
where
    T:VectorSize 
{
    for j in 0..T::DIMS {
        v0[j] *= f;
    }
}

playground