如何使用IMPL特质时获得DEREF胁迫(How to get Deref coercion whe

2019-09-26 00:18发布

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

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; 2] [usize; 2]而不是[usize] 编译器能够强迫&[T; 2] &[T; 2]&[T]如果我明确的告诉它到,例如,通过使用letstub()但如果我不这么做,这并不能够制定出胁迫是必需的。

但是,这是令人沮丧。 这是十分明显的人有什么失败调用打算这样做,编译器理解什么是需要的Vec<usize> Box<[usize]> Rc<[usize]> &[usize]等,所以它似乎并没有不合理的尝试,使之成为工作[usize; 2] [usize; 2]为好。

问:是否有写一个便捷的方式first()这样最后两个电话的工作吗? 如果没有,是否有一个语法要求编译器裹胁&[usize; 2] &[usize; 2]&[usize]直列, 不使用letstub()

游乐场 。

Answer 1:

你想用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);
}


文章来源: How to get Deref coercion when using impl Trait