代码之家  ›  专栏  ›  技术社区  ›  apt1002

使用impl-Trait时如何获得Deref强制

  •  1
  • apt1002  · 技术社区  · 7 年前

    此函数返回类似列表的集合的第一个元素。它适用于各种不同的列表类型:

    fn first<T: Copy>(x: impl Deref<Target=[T]>) -> T {
        x[0]
    }
    

    例如,它编译并运行:

    let data: Vec<usize> = vec![3, 4];
    assert_eq!(first(data), 3);
    
    let data: &[usize] = &[3, 4];
    assert_eq!(first(data), 3);
    
    let data: Rc<[usize]> = Rc::new([3, 4]);
    assert_eq!(first(data), 3);
    

    它还编译并运行:

    fn stub(x: &[usize]) -> usize {
        first(x)
    }
    
    let data: &[usize; 2] = &[3, 4];
    assert_eq!(stub(data), 3);
    
    assert_eq!(stub(&[3, 4]), 3);
    

    但这无法编译:

    let data: &[usize; 2] = &[3, 4];
    assert_eq!(first(data), 3); // Fails.
    
    assert_eq!(first(&[3, 4]), 3); // Fails.
    

    错误消息是:

    type mismatch resolving `<&[usize; 2] as std::ops::Deref>::Target == [_]`
    

    我想我明白发生了什么。每种类型 T 有一种独特的类型 <T as Deref>::Target . 什么时候 T &[usize; 2] [usize; 2] [usize] . 编译器能够强制 &[T; 2] &[T] let stub() ,但如果我不这样做,那么就无法确定是否需要强制。

    但这令人沮丧。对于人类来说,失败的调用的目的是什么是显而易见的,编译器也知道需要做什么 Vec<usize> Box<[usize]> , Rc<[usize]> , &[usize]

    first() 所以最后两个电话也能用?如果没有,是否有语法要求编译器强制 &[使用;2] &[使用] 不用 允许 ?

    Playground .

    1 回复  |  直到 7 年前
        1
  •  1
  •   Boiethios    7 年前

    AsRef Deref :

    use std::rc::Rc;
    
    fn first<T: Copy>(x: impl AsRef<[T]>) -> T {
        x.as_ref()[0]
    }
    
    fn main() {
        let data: Vec<usize> = vec![3, 4];
        assert_eq!(first(data), 3);
    
        let data: &[usize] = &[3, 4];
        assert_eq!(first(data), 3);
    
        let data: Rc<[usize]> = Rc::new([3, 4]);
        assert_eq!(first(data), 3);
    
        let data: &[usize; 2] = &[3, 4];
        assert_eq!(first(data), 3);
    }