< 返回版块

cybertheye 发表于 2024-03-21 18:48

Tags:rust, const,generics

https://practice.course.rs/generics-traits/const-generics.html 在看const泛型

fn foo<const N: usize>() {}

fn bar<T, const M: usize>() {
    foo::<M>(); // Okay: `M` is a const parameter
    foo::<2021>(); // Okay: `2021` is a literal
    foo::<{20 * 100 + 20 * 10 + 1}>(); // Okay: const expression contains no generic parameters
    
    foo::<{ M + 1 }>(); // Error: const expression contains the generic parameter `M`
    foo::<{ std::mem::size_of::<T>() }>(); // Error: const expression contains the generic parameter `T`
    
    let _: [u8; M]; // Okay: `M` is a const parameter
    let _: [u8; std::mem::size_of::<T>()]; // Error: const expression contains the generic parameter `T`
}

fn main() {}

这段代码里面 foo::<M>()是啥?和foo()有什么区别? 还有

/// A region of memory containing at least `N` `T`s.
pub struct MinSlice<T, const N: usize> {
    /// The bounded region of memory. Exactly `N` `T`s.
    pub head: [T; N],
    /// Zero or more remaining `T`s after the `N` in the bounded region.
    pub tail: [T],
}

fn main() {
    let slice: &[u8] = b"Hello, world";
    let reference: Option<&u8> = slice.get(6);
    // We know this value is `Some(b' ')`,
    // but the compiler can't know that.
    assert!(reference.is_some());

    let slice: &[u8] = b"Hello, world";
    // Length check is performed when we construct a MinSlice,
    // and it's known at compile time to be of length 12.
    // If the `unwrap()` succeeds, no more checks are needed
    // throughout the `MinSlice`'s lifetime.
    let minslice = MinSlice::<u8, 12>::from_slice(slice).unwrap();
    let value: u8 = minslice.head[6];
    assert_eq!(value, b' ')
}

这段代码中的let minslice = MinSlice::<u8, 12>::from_slice(slice).unwrap(); MinSlice::<u8, 12>是实例化的意思吗?(问的GPT,想确认一下)

评论区

写评论
潜水的猫 2024-03-23 16:25

就是传递泛型类型

樂見 2024-03-22 14:24

表达式中带有泛型参数的路径必须在左尖括号前加上一个 ::。 这种为表达泛型而结合起来形式(::<>)看起来有些像一条鱼。 因此,在口头上就被称为 turbofish句法。

turbofish-涡轮鱼,通常用于在表达式中为泛型类型、函数或方法指定参数。大部分时候当涉及到泛型时,编译器可以自动推断出泛型参数。但是有的时候,编译器需要一些帮助。

例如:

fn main()

let v = Vec::new(); 

       // ^^^^^^^^ cannot infer type for type parameter `T` 

 //

 // consider giving `v` the explicit type `Vec<T>`, where the type parameter `T` is specified

println!("{:?}", v);

}

以上出错,我们要么一、可以显示使用一个类型注解,二、绑定一个具体类型让编译器自动推导来解决它;要么通过一个叫做‘turbofish’ ::<> 的语法来绑定泛型参数T。 如下:

fn main() {

let v = Vec::<bool>::new(); //用‘turbofish’ ::<> 的语法来绑定泛型参数T

println!("{:?}", v);

}

这种方法在我们并不想要将结果绑定到一个变量时很有用。它也可以用来在函数和方法中绑定泛型参数。 你可以在编译器无法推断类型参数的任何情况下使用它,例如:

fn main () {

let a = (0..255).sum(); //error, cannot infer type 

let b = (0..255).sum::<u32>(); 

let c: u32 = (0..255).sum();

}

//a不起作用,因为它不能推断变量类型。 //b确实有效,因为我们直接用turbofish语法指定类型参数。 //c是可行的,因为我们直接显示指定了c的类型。

Mike Tang 2024-03-22 02:21

就是给编译器提供充足的类型信息,是类型参数T的具化。

作者 cybertheye 2024-03-21 21:41

额,就是不是很懂这个调用方式,foo::()后面怎么还要加个::,其他语言过来的感觉是在访问成员变量啥的

--
👇
TinusgragLin: 我的理解是这些就是告诉编译器到底要编译什么。通常编译器会自己推断,但是信息不够的情况下就会: 编译器:哇,这个结构体存了个T.....所以里面到底要存什么?这个函数说它会对输入的T进行一个加 1...干!我怎么知道T能不能加一喽,再说加一的实现那么多,我怎么知道是哪个咧?

TinusgragLin 2024-03-21 19:19

我的理解是这些就是告诉编译器到底要编译什么。通常编译器会自己推断,但是信息不够的情况下就会: 编译器:哇,这个结构体存了个T.....所以里面到底要存什么?这个函数说它会对输入的T进行一个加 1...干!我怎么知道T能不能加一喽,再说加一的实现那么多,我怎么知道是哪个咧?

1 共 5 条评论, 1 页