- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这段代码定义了一个非常简单的特征来表示二叉树和一个实现该特征的结构:
pub trait BTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)>;
fn left(&self) -> Option<&Self>;
fn right(&self) -> Option<&Self>;
fn value(&self) -> Option<&T>;
}
pub struct MyBTree<T> {
opt: Option<Box<(MyBTree<T>, MyBTree<T>, T)>>,
}
impl<T> BTree<T> for MyBTree<T> {
fn all(&self) -> Option<(&Self, &Self, &T)> {
match self.opt {
None => None,
Some(ref tuple) => Some((&tuple.0, &tuple.1, &tuple.2)),
}
}
fn left(&self) -> Option<&Self> {
match self.all() {
None => None,
Some((left, _, _)) => Some(left),
}
}
fn right(&self) -> Option<&Self> {
match self.all() {
None => None,
Some((right, _, _)) => Some(right),
}
}
fn value(&self) -> Option<&T> {
match self.all() {
None => None,
Some((_, _, value)) => Some(value),
}
}
}
left
、right
和 value
的实现可以移动到 trait 内部,因为它们只依赖于 all
由特征定义的方法,而不是实现细节。
这适用于 value
,但 不适用于 left
和 right
。例如,如果我尝试在特征主体中移动 left
的实现,我会得到以下编译错误:
error[E0311]: the parameter type `T` may not live long enough
--> src/lib.rs:6:24
|
6 | match self.all() {
| ^^^
|
= help: consider adding an explicit lifetime bound for `T`
note: the parameter type `T` must be valid for the anonymous lifetime #1 defined on the method body at 5:9...
--> src/lib.rs:5:9
|
5 | / fn left(&self) -> Option<&Self> {
6 | | match self.all() {
7 | | None => None,
8 | | Some((left, _, _)) => Some(left),
9 | | }
10| | }
| |_________^
note: ...so that the reference type `&T` does not outlive the data it points at
--> src/lib.rs:6:24
|
6 | match self.all() {
|
为什么这个问题出现在 trait 而不是 MyBTree
的实现中?
为什么编译器在忽略 T 值的方法中提示 T
的生命周期——而它与方法 value
一起工作> 哪个在其返回类型中提到了 T?
最佳答案
How come this problem occurs in the trait, but not in its implementation for MyBTree?
当您考虑实现 BTree<T>
时,这些方法签名会变得更加微妙对于具有生命周期的类型。我对涉及泛型类型参数或 Self
的所有生命周期错误的一般建议type is:关注类型是借用类型的情况。
借用类型的问题在于,您永远无法拥有比它所引用的数据更长生命周期的引用。此原则的最简单示例是:
fn f<'a, 'b>() {
// error[E0491]: in type `&'a &'b ()`, reference has a longer
// lifetime than the data it references
let _: &'a &'b ();
}
Rust 强制我们保证引用引用的数据比引用更有效,在本例中为 'b
超过生命周期'a
.
fn f<'a, 'b: 'a>() {
let _: &'a &'b ();
}
现在让我们将其应用到您的 BTree
如果T
会出现什么问题是借来的类型,如 &()
.首先,查看您放置在 impl<T> BTree<T> for MyBTree<T>
中的以下两个方法.我明确写下了省略的生命周期以澄清讨论。
impl<T> BTree<T> for MyBTree<T> {
fn left<'a>(&'a self) -> Option<&'a Self> { /* ... */ }
fn value<'a>(&'a self) -> Option<&'a T> { /* ... */ }
}
为了调用者调用left
,他们必须知道 Self
生命周期超过生命周期 'a
.为了调用者调用 value
他们必须知道Self
生命周期超过生命周期 'a
和 T
生命周期超过生命周期 'a
(为了使 &'a T
成为有意义的类型,正如我们在上面看到的)。除非满足这些要求,否则借用检查器不会让他们调用这些方法,因此实现可以假定满足这些要求。
此外,借用检查器可以看到if Self
超过生命周期'a
然后还有T
超过生命周期'a
因为MyBTree<T>
包含 T
类型的值.
这就是为什么执行 left
没有问题的原因和 value
在 impl<T> BTree<T> for MyBTree<T>
内.来电者和 MyBTree<T>
一起构建保证一切都在我们需要的时候存在。
现在,如果我们在 BTree<T>
中有这些方法特征定义。
trait BTree<T> {
fn left<'a>(&'a self) -> Option<&'a Self> { /* ... */ }
fn value<'a>(&'a self) -> Option<&'a T> { /* ... */ }
}
这里出了问题,因为如果调用者调用 left
他们必须知道Self
超过生命周期'a
,但他们没有保证 T
超过生命周期'a
.例如,他们可以有 T=&'b ()
对于一些完全不相关的较短生命周期 'b
.正如我们在上面看到的,这将使 &'a T
等于 &'a &'b ()
这不是合法类型。
Rust 对 value
满意的原因特征中定义的是调用者保证Self
和 T
超过输入生命周期 'a
. Rust 对 left
不满意的原因特征中定义的是调用者只保证 Self
超过生命周期'a
, 不是 T
超过生命周期'a
实现假设。
And how come the compiler complains about the lifetime of T in the methods who ignore the T value -- while it works with the method
value
which does mention T in its return type?
好吧,错误与返回值无关,而是与对 all()
的调用有关.仔细看。
error[E0311]: the parameter type `T` may not live long enough
--> src/lib.rs:6:24
|
6 | match self.all() {
| ^^^
为了调用all()
,调用者负责证明输入和输出类型是有效类型。但在 T
的情况下类似于 &'b ()
,这可能不是真的。 all()
会返回 &'a &'b ()
所以借用检查器会阻止调用。
我们可以通过明确我们的实现假设的保证来解决这个问题,在这种情况下 T
超过生命周期'a
.
trait BTree<T> {
fn left<'a>(&'a self) -> Option<&'a Self>
where
T: 'a,
{
/* ... */
}
}
关于rust - 为什么函数体在结构中编译,而不是在特征中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49034550/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!