- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个带有边和节点的图形实现。该图应同时访问,因此我选择将边和节点构建为 Arc<Mutex<dyn Edge>>
和 Arc<RwLock<dyn Node>>
.
不幸的是我得到一个编译错误the parameter type 'T' may not live long enough
( Playground ) 连接节点/边时。
pub trait Node {
fn connect(&mut self, edge: EdgeRef);
}
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub trait Edge {
fn connect(&mut self, node: NodeRef);
}
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
impl<T> Node for Arc<RwLock<T>>
where
T: Node,
{
fn connect(&mut self, edge_ref: EdgeRef) {
let mut node = self.write().unwrap();
let mut edge = edge_ref.lock().unwrap();
let self_clone = self.clone() as NodeRef; // the parameter type `T` may not live long enough
edge.connect(self_clone);
node.connect(edge_ref.clone());
}
}
问题是:一个Arc<RwLock<T>>
应该不是引用,所以不应该有生命周期。将其转换为 Arc<RwLock<dyn Node>>
也不引入生命周期。
有人可以解释这个编译器错误吗?这个问题是与每个参数类型(例如 Type<T>
)相关还是仅与 Arc<RwLock<T>>
相关? ?
最佳答案
编译错误解释了如何解决问题:
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:22:22
|
15 | impl<T> Node for Arc<RwLock<T>>
| - help: consider adding an explicit lifetime bound...: `T: 'static`
...
22 | let self_clone = self.clone() as NodeRef;
| ^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> src/lib.rs:22:22
|
22 | let self_clone = self.clone() as NodeRef;
| ^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0310`.
添加+ 'static
给你的T
的边界确实修复了错误:
use std::sync::{Arc, Mutex, RwLock};
pub trait Node {
fn connect(&mut self, edge: EdgeRef);
}
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub trait Edge {
fn connect(&mut self, node: NodeRef);
}
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
impl<T> Node for Arc<RwLock<T>>
where
T: Node + 'static, // added "+ 'static" here
{
fn connect(&mut self, edge_ref: EdgeRef) {
let mut node = self.write().unwrap();
let mut edge = edge_ref.lock().unwrap();
let self_clone = self.clone() as NodeRef;
edge.connect(self_clone);
node.connect(edge_ref.clone());
}
}
但是当我的 T 永远不会成为引用时,为什么我需要终生绑定(bind)? 你问。好吧,Rust 编译器还不知道,一个 T
可以是任何类型,包括引用。 T
表示的类型集包括由 &T
表示的类型集和 &mut T
.两者 &T
和 &mut T
是 T
的子集.这就是为什么你必须将生命周期限制在 T
上,这是您与编译器沟通的方式,您的 T
将只拥有类型或静态引用。
更多关于“静态生命周期”
'static
是一生的误导性名称,因为它会让大多数人认为 'static
类型必须在程序的整个持续时间内都存在,并且不能动态分配或删除。这些在现实中都不是真的:'static
类型可以动态分配,也可以删除。什么'static
在实践中真正的意思是“你可以无限期地安全地持有这种类型”。所有“拥有的类型”,如 String
和 Vec
是'static
.这是一个 Rust 程序,我希望它能说明这一点:
use rand::prelude::*; // 0.7.3
// this function takes 'static types and drops them
// no compiler errors because 'static types can be dynamically allocated and dropped
fn is_static<T: 'static>(t: T) {
std::mem::drop(t)
}
fn main() {
let string = String::from("string"); // dynamically allocated string
is_static(string); // compiles just fine
let mut strings: Vec<String> = Vec::new();
let mut loops = 10;
while loops > 0 {
if rand::random() {
strings.push(format!("randomly dynamically allocated string on loop {}", loops));
}
loops -= 1;
}
// all the strings are 'static
for string in strings {
is_static(string); // compiles no problem
}
}
关于生命周期省略和默认特征对象生命周期的更多信息
你定义NodeRef
和 EdgeRef
因此:
pub type NodeRef = Arc<RwLock<dyn Node>>;
pub type EdgeRef = Arc<Mutex<dyn Edge>>;
但是 Rust 编译器会这样解释:
pub type NodeRef = Arc<RwLock<dyn Node + 'static>>;
pub type EdgeRef = Arc<Mutex<dyn Edge + 'static>>;
所以当你想投一些Arc<RwLock<T>>
至 NodeRef
然后 T
必须以 Node + 'static
为界因为NodeRef
也有这些界限,即 Arc<RwLock<dyn Node + 'static>>
. Rust 中的所有特征对象都有生命周期,但您通常不会编写它们,因为 Rust 会为您推断它们。 The Rust Reference has a thorough explanation on lifetime elision and default trait object lifetimes如果您想了解更多信息。
你可以缓解 'static
通过使您的类型别名在 'a
上通用来满足要求:
pub type NodeRef<'a> = Arc<RwLock<dyn Node + 'a>>;
pub type EdgeRef<'a> = Arc<Mutex<dyn Edge + 'a>>;
然而,这会显着增加代码的复杂性,我敢肯定你想坚持使用 'static
因为它已经支持您正在尝试做的事情。
关于generics - 将 Arc<RwLock<T>> 转换为 Arc<RwLock<TraitObject>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61712044/
我对这个错误很困惑: Cannot implicitly convert type 'System.Func [c:\Program Files (x86)\Reference Assemblies\
考虑这段代码: pub trait Hello { fn hello(&self); } impl Hello for Any { fn hello(&self) {
问题很简单。是否可以构造这样一个类型 T,对于它下面的两个变量声明会产生不同的结果? T t1 = {}; T t2{}; 我已经研究 cppreference 和标准一个多小时了,我了解以下内容:
Intellij idea 给我这个错误:“Compare (T, T) in Comparator cannot be applied to (T, T)” 对于以下代码: public class
任何人都可以告诉我 : n\t\t\t\t\n\t\t\t 在以下来自和 dwr 服务的响应中的含义和用途是什么. \r\n\t\t\t \r\n\t\t\t
让 T 成为一个 C++ 类。 下面三个指令在行为上有什么区别吗? T a; T a(); T a = T(); T 为不带参数的构造函数提供了显式定义这一事实是否对问题有任何改变? 后续问题:如果
Rust中的智能指针是什么 智能指针(smart pointers)是一类数据结构,是拥有数据所有权和额外功能的指针。是指针的进一步发展 指针(pointer)是一个包含内存地
比如我有一个 vector vector > v={{true,1},{true,2},{false,3},{false,4},{false,5},{true,6},{false,7},{true,8
我有一个来自 .xls 电子表格的数据框,我打印了 print(df.columns.values) 列,输出包含一个名为:Poll Responses\n\t\t\t\t\t。 我查看了 Excel
This question already has answers here: What are good reasons for choosing invariance in an API like
指针类型作为类型前缀与在类型前加斜杠作为后缀有什么区别。斜线到底是什么意思? 最佳答案 语法 T/~ 和 T/& 基本上已被弃用(我什至不确定编译器是否仍然接受它)。在向新向量方案过渡的初始阶段,[T
我正在尝试找到一种方法来获取模板参数的基类。 考虑以下类: template class Foo { public: Foo(){}; ~Foo(){};
这是一个让我感到困惑的小问题。我不知道如何描述它,所以只看下面的代码: struct B { B() {} B(B&) { std::cout ::value #include
为什么有 T::T(T&) 而 T::T(const T&) 更适合 copy ? (大概是用来实现move语义的???) 原始描述(被melpomene证明是错误的): 在C++11中,支持了一种新
在 Java 7 中使用 eclipse 4.2 并尝试实现 List 接口(interface)的以下方法时,我收到了警告。 public T[] toArray(T[] a) { ret
假设有三个函数: def foo[T](a:T, b:T): T = a def test1 = foo(1, "2") def test2 = foo(List(), ListBuffer()) 虽
我对柯里化(Currying)和非柯里化(Currying)泛型函数之间类型检查的差异有点困惑: scala> def x[T](a: T, b: T) = (a == b) x: [T](a: T,
考虑一个类A,我如何编写一个具有与相同行为的模板 A& pretty(A& x) { /* make x pretty */ return x; } A pretty(A&& x) {
Eclipse 表示由于泛型类型橡皮擦,类型参数不允许使用 instanceof 操作。 我同意在运行时不会保留任何类型信息。但是请考虑以下类的通用声明: class SomeClass{ T
在 C++14 中: 对于任何整数或枚举类型 T 以及对于任何表达式 expr: 有没有区别: struct S { T t { expr }; }; 和 struct S { T t = { exp
我是一名优秀的程序员,十分优秀!