Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何在使用impl Trait时获得Deref强制(第2步)_Rust_Traits_Coercion - Fatal编程技术网

Rust 如何在使用impl Trait时获得Deref强制(第2步)

Rust 如何在使用impl Trait时获得Deref强制(第2步),rust,traits,coercion,Rust,Traits,Coercion,下面是一个特性(针对问题进行了简化),我想为每种行为类似于切片的类型实现它: trait SliceLike { type Item; /// Computes and returns (owned) the first item in a collection. fn first_item(&self) -> Self::Item; } 请注意,项类型是关联类型;我希望SliceLike的每个类型都有一个唯一的元素类型 下面是一个全面实施的尝试: us

下面是一个特性(针对问题进行了简化),我想为每种行为类似于切片的类型实现它:

trait SliceLike {
    type Item;

    /// Computes and returns (owned) the first item in a collection.
    fn first_item(&self) -> Self::Item;
}
请注意,
类型是关联类型;我希望
SliceLike
的每个类型都有一个唯一的元素类型

下面是一个全面实施的尝试:

use std::ops::Deref;

impl<T: Clone, U: Deref<Target = [T]>> SliceLike for U {
    type Item = T;

    fn first_item(&self) -> Self::Item {
        self[0].clone()
    }
}
但是如果我内联
stub()
它将无法编译:

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

assert_eq!([3, 4].first_item(), 3); // Fails.
总括实现使用编译器本身用来将其他类型转换为片的
Deref
特性。它将捕获所有行为类似于切片的第三方类型

错误消息是:

error[E0599]:在当前作用域中找不到类型“[usize;2]”名为“first\u item”的方法
-->src/lib.rs:20:21
|
20 |断言| eq!(data.first_item(),3);//失败。
|                     ^^^^^^^^^^
|
=注意:方法“first_item”存在,但不满足以下特征界限:
`[用法;2]:像`
`[用法]:像`
=帮助:只有在trait已实现且在范围内时,才能使用trait中的项
=注意:以下特征定义了一个项“first\u item”,可能您需要实现它:
候选人#1:`像切片机一样`
在这个问题中,有人建议我使用
AsRef
而不是
Deref
。该解决方案在这里不起作用,因为某些类型可能对多个元素类型实现
AsRef

我想我明白发生了什么。对于每个类型
T
都有一个唯一的类型
::Target
。当
T
&[usize;2]
时,目标是
[usize;2]
,而不是
[usize]
。如果我明确要求编译器将
&[T;2]
强制为
&[T]
,例如使用
let
stub()
,编译器可以强制为
&[T]
,但如果我不这样做,则无法确定强制是必需的

但它令人沮丧:对于人类来说,失败调用的意图是什么是显而易见的,而且编译器理解
Vec
Box
Rc
&[usize]
等等所需的内容,因此尝试让它也为
[usize;2]
工作似乎并不不合理

是否有一种方便的方法来编写
first()
,以便最后两个调用也能工作?如果没有,是否有语法要求编译器将
&[usize;2]
强制为
&[usize]
内联,即不使用
let
存根()


Deref
是为、实现的,而数组(
[t;N]
)没有实现,这就是为什么
[3,4]。第一项()不起作用


无法为
[t;N]
实现
Deref
,因为必须以某种方式将数组强制为片。我所知道的最佳方法如下:

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

请注意,这样的问题可能会在合并后消失。

impl-SliceLike for[T]
有什么问题吗?它当然满足一些要求。它允许您在许多有趣的类型上调用
SliceLike
方法。然而,它不会满足诸如
Vec:SliceLike
之类的特征边界,因此它会使编写在
SliceLike
类型上多态的代码变得更加困难。我认为不可能同时拥有你的建议impl和我的建议impl,因为理论上可能[T]会在未来某个日期实施Deref。“由于连贯性规则,
[T;N]
[3,4],不可能对
[T;N]
实施
,而且更容易阅读。我想没关系。
let data: [usize; 2] = [3, 4];
assert_eq!(data.first_item(), 3); // Fails.

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