You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1.7 KiB

Deref

下面的代码会报错

use std::ops::Index;
use std::rc::Rc;

struct MyType<T> { bytes: T }

// Wow such clean much wow
impl<T: Index<I>, I> Index<I> for MyType<T> {
    type Output = T::Output;

    fn index(&self, index: I) -> &Self::Output {
        &self.bytes[index]
    }
}

fn main() {
    let rc1 = Rc::new([1, 2, 3]);
    rc1[0]; // OK

    let rc2 = MyType { bytes: Rc::new([1, 2, 3]) };
    rc2[0]; // error[E0608]: cannot index into a value of type `MyType<Rc<[{integer}; 3]>>`
           // WHY???!?!!?!?!?!?
}

报错的原因是Rc自身没有实现Index<usize>,因此需要先通过Deref转为内部的数据类型,再进行索引。

首先let rc1 = Rc::new([1, 2, 3]);能行,是因为Rc能通过Deref转为&[]类型,因此Deref后,等同于直接对内部的数组切片取索引.

let rc2 = MyType { bytes: Rc::new([1, 2, 3]) };不行,是因为Rc::new([1,2,3])实际上是泛型类型T编译器并不知道T有没有实现Deref,因此也不能对Rc::new([1,2,3])进行索引。

简而言之,只有作为表达式才能自动进行Deref(rc1),作为泛型类型时,不能自动进行Deref(rc2)。

你也可以为自己的类型实现Deref:

use std::ops::Deref;
use std::rc::Rc;

struct MyType<T> { bytes: T }

impl<T> Deref for MyType<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.bytes
    }
}

fn main() {
    let rc = Rc::new([1, 2, 3]);
    rc[0]; // OK

    let rc = MyType { bytes: Rc::new([1, 2, 3]) };
    rc[0];
}

但是这不符合官方推荐的使用方式,因为官方明确推荐Deref适用于智能指针,其它类型要小心使用。