- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是我想为每个行为类似于切片的类型实现的特征(针对问题进行了简化):
trait SliceLike {
type Item;
/// Computes and returns (owned) the first item in a collection.
fn first_item(&self) -> Self::Item;
}
请注意 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()
}
}
例如,编译并运行:
let data: Vec<usize> = vec![3, 4];
assert_eq!(data.first_item(), 3);
let data: &[usize] = &[3, 4];
assert_eq!(data.first_item(), 3);
let data: Box<[usize]> = Box::new([3, 4]);
assert_eq!(data.first_item(), 3);
let data: Rc<[usize]> = Rc::new([3, 4]);
assert_eq!((&data).first_item(), 3);
这也编译并运行:
fn stub(x: &[usize]) -> usize {
x.first_item()
}
let data: [usize; 2] = [3, 4];
assert_eq!(stub(&data), 3);
assert_eq!(stub(&[3, 4]), 3);
但是如果我内联 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]: no method named `first_item` found for type `[usize; 2]` in the current scope
--> src/lib.rs:20:21
|
20 | assert_eq!(data.first_item(), 3); // Fails.
| ^^^^^^^^^^
|
= note: the method `first_item` exists but the following trait bounds were not satisfied:
`[usize; 2] : SliceLike`
`[usize] : SliceLike`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `first_item`, perhaps you need to implement it:
candidate #1: `SliceLike`
在take 1关于这个问题,有人建议我使用 AsRef
而不是 Deref
.该解决方案在这里不起作用,因为某些类型可能会实现 AsRef
对于不止一种元素类型。
我想我明白发生了什么。对于每种类型 T
有一个独特的类型 <T as Deref>::Target
.当T
是&[usize; 2]
目标是 [usize; 2]
, 不是 [usize]
.编译器能够强制 &[T; 2]
至 &[T]
如果我明确要求它,例如通过使用 let
或 stub()
,但如果我不这样做,那么就无法确定需要强制转换。
但这令人沮丧:对于人类来说,失败调用的目的是显而易见的,编译器理解 Vec<usize>
需要什么。 , Box<[usize]>
, Rc<[usize]>
, &[usize]
依此类推,因此尝试使其适用于 [usize; 2]
似乎并不合理
有没有方便的写法first()
这样最后两个电话也可以吗?如果不是,是否有语法要求编译器强制执行 &[usize; 2]
到 &[usize]
内联,即 不使用 let
或 stub()
?
最佳答案
Deref
为 Vec
实现, Box
, Rc
, &T where T: ?Sized
并且没有数组的实现( [T; N]
),这就是为什么 [3, 4].first_item()
不起作用。
无法实现 Deref
对于 [T; N]
由于coherence rules ,因此,必须以一种或另一种方式将数组强制转换为切片。我知道的最好的方法如下:
let data: [usize; 2] = [3, 4];
assert_eq!((&data[..]).first_item(), 3); // Ok
请注意,像这样的问题可能会消失一次const generic合并。
关于rust - 使用 impl Trait 时如何获得 Deref 强制转换(第 2 课),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54451342/
我正在阅读 Rust 的 Deref 文档特点: pub trait Deref { type Target: ?Sized; fn deref(&self) -> &Self::Ta
下面是Deref example from The Rust Programming Language除了我添加了另一个断言。 为什么 assert_eq 和 deref 也等于 'a'?为什么在手动
我想实现 Deref和 DefrefMut在拥有盒装特征的结构上,例如: use std::ops::{Deref, DerefMut}; trait Quack { fn quack(&se
这个问题在这里已经有了答案: Why is the return type of Deref::deref itself a reference? (2 个回答) 1年前关闭。 例如,我有一个实现了
来自 clojure 为勇敢而真实的人: (defmacro enqueue [q concurrent-promise-name & work] (let [concurrent (butl
我正在传递一个链表,其中包含另一个链表到一个函数,但我在从传递的双指针中取消/引用内部链表时遇到问题。 push(*config->inner_linked_list... 行的编译器错误是 '*co
我正在尝试为枚举实现Deref: use std::rc::Rc; use std::ops::Deref; pub trait tObject { fn name(&self) -> Str
我需要为来自外部 crate 的对象实现 fmt::Display 方法,因此我为该对象创建了一个包装器。我希望能够使用原始对象的所有方法,而不必重新定义所有方法。我尝试按照很棒的 IRC chann
这个问题在这里已经有了答案: Why is the return type of Deref::deref itself a reference? (2 个答案) 关闭 5 年前。 以下代码: us
我有: struct Id; struct Url; struct IdAndUrl { id: Id, url: Url, } 我希望能够使用 IdAndUrl在我需要的地方 Id
我经常使用 newtype 模式,但我厌倦了编写 my_type.0.call_to_whatever(...)。我很想实现 Deref 特性,因为它允许编写更简单的代码,因为在某些情况下我可以使用我
我在 Rust 中编写一个 Vector 类只是为了好玩,我认为能够为它实现 Deref 会很好,就像访问元组引用一样访问它。例如,Vec2可以取消引用为 &(f32, f32) .我想到了这个: p
如果能够使用 Deref 从通用容器生成 &TraitType,而不是调用 instance.as_ref() 会更方便。即: (*my_container).do_thing(); 对比 my_co
在这段代码之前,我以为我了解了移动语义。 fn main() { let v = Data { body: vec![10, 40, 30], }; p(&v)
我有一个实现Deref的结构: pub struct Foo { val: u8, } impl Deref for Foo { type Target = u8; fn de
class DogOwner { Dog dog; DogOwner(Dog dog) { this.dog = dog; } } class Dog {
我在尝试将 impl Add for String 添加到标准库时遇到了这个问题。但是我们可以轻松复制它,无需运算符(operator)恶作剧。我们从这个开始: trait MyAdd { f
在阅读了关于 Smart Pointers and Interior mutability 的 Rust 书中的部分之后,作为个人练习,我尝试编写一个函数,该函数将遍历智能指针的链表并返回列表中的“最
这里是 example of usage Deref 的修改版本: use std::ops::Deref; use std::rc::Rc; #[derive(Clone, PartialEq, H
我有一个 String newtype ErrorMessage 我在原型(prototype)箱中用于错误。 (我知道这是一种不好的做法。我将在发布之前构建一组适当的不同错误类型。) 我需要 Err
我是一名优秀的程序员,十分优秀!