首页 > 解决方案 > 我可以只用一个类型而不是一个具体变量来获得一个 Rust 数组的长度吗?

问题描述

我想将以下 C++ 代码重写为 Rust:

using storage = array<int, 3>;
const size_t storage_len = sizeof(storage) / sizeof(storage::value_type);

如何在没有具体变量的情况下获得该恒定长度值?

作为动机,虽然它可能看起来微不足道,但我想在不声明变量的情况下打印数组的元素计数。我知道我可以使用常量值或声明一个虚拟变量,但我想知道 Rust 如何保留 C++ 代码。

我承认没有具体的变量是不清楚的。我想实现上述 C++ 功能,但这种解释可能会产生误导。我很好奇是否有任何方法可以获取数组的元素类型。

标签: arraysrustdependent-typeconstant-expression

解决方案


Rust 现在支持 const 泛型。我留下了旧答案,所以人们知道为什么有人可能会首先问这个问题。

自 Rust 1.51 以来的新答案

pub trait Length {
    const LEN: usize;
}

impl<T, const LENGTH: usize> Length for [T; LENGTH] {
    const LEN: usize = LENGTH;
}

旧答案

我了解您想仅从类型信息中检索数组长度。Rust 没有内置的 PI 类型(又名const generics)。这意味着该语言目前不支持非类型的泛型参数如数组长度的整数)。

跟踪此问题存在一个问题,我们可能会在未来看到对它的支持,尽管不是在不久的将来。

如果必须,您可以通过为每种类型实现一个特征来解决该限制:

trait GetLength {
    fn len() -> usize;
}

impl<T> GetLength for [T; 0] {
    fn len() -> usize {
        0
    }
}

impl<T> GetLength for [T; 1] {
    fn len() -> usize {
        1
    }
}

// ...

fn main() {
    println!("{}", <[String; 1]>::len());
}

宏可以帮助防止重复输入:

trait GetLength {
    fn len() -> usize;
}

macro_rules! impl_get_length {
    ($v:expr) => {
        impl<T> GetLength for [T; $v] {
            fn len() -> usize {
                $v
            }
        }
    };
}

impl_get_length!{ 0 }
impl_get_length!{ 1 }

// ...

fn main() {
    println!("{}", <[String; 1]>::len());
}

类似的板条箱typenum也有助于为现有语言中的 const 泛型提供一些支持。


推荐阅读