我可以仅使用类型而不是具体变量来获取 Rust 数组的长度吗?
Can I get a Rust array's length with only a type, not a concrete variable?
我想将以下 C++ 代码重写为 Rust:
using storage = array<int, 3>;
const size_t storage_len = sizeof(storage) / sizeof(storage::value_type);
如何在没有具体变量的情况下获得该恒定长度值?
作为动机,虽然这看起来微不足道,但我想在不声明变量的情况下打印数组的元素计数。我知道我可以使用常量值或声明一个虚拟变量,但我想知道 Rust 如何保存 C++ 代码。
我承认没有具体变量不清楚。我想实现上述 C++ 功能,但这种解释可能会产生误导。我很好奇是否有任何方法可以获取数组的元素类型。
在 Rust 中,您可以使用 std::mem::size_of
获取类型的大小,因此您可以像在 C++ 中一样获取数组类型的长度:
use std::mem::size_of;
type Storage = [i32; 3];
fn main() {
println!("Length: {}", size_of::<Storage>() / size_of::<i32>());
}
然而,这需要知道存储在数组中的项目的类型。我不知道有什么方法可以在不实例化变量的情况下获得它。
您可以使用 mem::size_of
:
let storage_len = std::mem::size_of::<[i32; 3]>() / std::mem::size_of::<i32>();
Arrays coerce to slices, so any method available on slices are also available on arrays. Like len()
:
let v = [0u32; 128];
assert_eq!(128, v.len());
Rust 现在支持常量泛型。我留下了旧的答案,这样人们就会知道为什么有人会首先问这个问题。
自 Rust 1.51 以来的新答案:
pub trait Length {
const LEN: usize;
}
impl<T, const LENGTH: usize> Length for [T; LENGTH] {
const LEN: usize = LENGTH;
}
旧答案:
我了解到您想仅从类型信息中检索数组长度。 Rust 没有内置的 PI 类型(a.k.a。const generics)。这意味着语言目前不支持非类型的通用参数(例如数组长度的整数)。
有 an issue tracking this,我们很可能会在未来看到对它的支持,尽管不会在不久的将来。
如有必要,您可以通过为每种类型实现一个特征来解决该限制:
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
这样的 crate 也有助于在现有语言中为 const 泛型提供一些支持。
纯属娱乐:
use std::mem;
use std::ops::Deref;
fn main() {
assert_eq!(5, num_elems::<[i32; 5]>());
}
fn num_elems<T>() -> usize
where
T: 'static,
&'static T: IntoIterator,
<&'static T as IntoIterator>::Item: Deref,
<<&'static T as IntoIterator>::Item as Deref>::Target: Sized,
{
fn inner<S, I>() -> usize
where
I: Deref,
<I as Deref>::Target: Sized,
{
mem::size_of::<S>() / mem::size_of::<I::Target>()
}
inner::<T, <&'static T as IntoIterator>::Item>()
}
这适用于最多 32 个元素的任何数组,如果数组元素类型为零大小,则会出现恐慌。另外,除了数组类型,你还可以使用其他东西,我不知道它会做什么。
我想将以下 C++ 代码重写为 Rust:
using storage = array<int, 3>;
const size_t storage_len = sizeof(storage) / sizeof(storage::value_type);
如何在没有具体变量的情况下获得该恒定长度值?
作为动机,虽然这看起来微不足道,但我想在不声明变量的情况下打印数组的元素计数。我知道我可以使用常量值或声明一个虚拟变量,但我想知道 Rust 如何保存 C++ 代码。
我承认没有具体变量不清楚。我想实现上述 C++ 功能,但这种解释可能会产生误导。我很好奇是否有任何方法可以获取数组的元素类型。
在 Rust 中,您可以使用 std::mem::size_of
获取类型的大小,因此您可以像在 C++ 中一样获取数组类型的长度:
use std::mem::size_of;
type Storage = [i32; 3];
fn main() {
println!("Length: {}", size_of::<Storage>() / size_of::<i32>());
}
然而,这需要知道存储在数组中的项目的类型。我不知道有什么方法可以在不实例化变量的情况下获得它。
您可以使用 mem::size_of
:
let storage_len = std::mem::size_of::<[i32; 3]>() / std::mem::size_of::<i32>();
Arrays coerce to slices, so any method available on slices are also available on arrays. Like len()
:
let v = [0u32; 128];
assert_eq!(128, v.len());
Rust 现在支持常量泛型。我留下了旧的答案,这样人们就会知道为什么有人会首先问这个问题。
自 Rust 1.51 以来的新答案:
pub trait Length {
const LEN: usize;
}
impl<T, const LENGTH: usize> Length for [T; LENGTH] {
const LEN: usize = LENGTH;
}
旧答案:
我了解到您想仅从类型信息中检索数组长度。 Rust 没有内置的 PI 类型(a.k.a。const generics)。这意味着语言目前不支持非类型的通用参数(例如数组长度的整数)。
有 an issue tracking this,我们很可能会在未来看到对它的支持,尽管不会在不久的将来。
如有必要,您可以通过为每种类型实现一个特征来解决该限制:
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
这样的 crate 也有助于在现有语言中为 const 泛型提供一些支持。
纯属娱乐:
use std::mem;
use std::ops::Deref;
fn main() {
assert_eq!(5, num_elems::<[i32; 5]>());
}
fn num_elems<T>() -> usize
where
T: 'static,
&'static T: IntoIterator,
<&'static T as IntoIterator>::Item: Deref,
<<&'static T as IntoIterator>::Item as Deref>::Target: Sized,
{
fn inner<S, I>() -> usize
where
I: Deref,
<I as Deref>::Target: Sized,
{
mem::size_of::<S>() / mem::size_of::<I::Target>()
}
inner::<T, <&'static T as IntoIterator>::Item>()
}
这适用于最多 32 个元素的任何数组,如果数组元素类型为零大小,则会出现恐慌。另外,除了数组类型,你还可以使用其他东西,我不知道它会做什么。