我有以下定义:
struct MyCustomFactory;
trait Factory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized;
}
impl Factory for MyCustomFactory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized,
{
Arc::new(entity)
}
}
Run Code Online (Sandbox Code Playgroud)
更高层次的问题:
我正在尝试创建一个全局静态(且不可变)的字符串映射到实现该Factory特征的结构。目标是,对于映射的任何值成员,我可以将其视为 a Factory,new对其进行调用,然后将得到(在本例中)实现该特征的东西Display。
我有以下内容:
struct MyCustomFactory;
trait Factory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized;
}
impl Factory for MyCustomFactory {
fn new<'a>(entity: &'a str) -> Arc<dyn Display + 'a>
where
Self: Sized,
{
Arc::new(entity)
}
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨:
static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
Lazy::new(|| {
let mut map = BTreeMap::new();
let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
map.insert("foo", value);
map
});
Run Code Online (Sandbox Code Playgroud)
我尝试过的事情:
Sync针对特征实施:声明该特征具有trait Factory : Sync(意味着实现该特征的所有项目都必须实现Sync)和/或定义:
77 | / static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory>>> =
78 | | Lazy::new(|| {
79 | | let map = BTreeMap::new();
80 | | let value = Arc::new(MyCustomFactory) as Arc<dyn Factory>;
... |
88 | | });
| |_______^ `(dyn Factory + 'static)` cannot be shared between threads safely
|
= help: the trait `std::marker::Sync` is not implemented for `(dyn Factory + 'static)`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::sync::Arc<(dyn Factory + 'static)>`
= note: required because of the requirements on the impl of `std::marker::Send` for `alloc::collections::btree::node::Root<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because it appears within the type `std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::imp::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because it appears within the type `once_cell::sync::OnceCell<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: required because of the requirements on the impl of `std::marker::Sync` for `once_cell::sync::Lazy<std::collections::BTreeMap<&'static str, std::sync::Arc<(dyn Factory + 'static)>>>`
= note: shared static variables must have a type that implements `Sync`
Run Code Online (Sandbox Code Playgroud)换行Arc<dyn Factory>:我尝试使用Mutex/ RefCell/OnceCell和其他方法,都导致了相同的错误。似乎应该有一种方法将底层MyCustomFactory视为可以锁定的单例。很好(也是预期的),这个结构在全球范围内只有一个实例。
您已接近添加Sync. 如果仔细观察,您会发现该错误然后建议添加Send:
= help: the trait `std::marker::Send` is not implemented for `(dyn Factory + 'static)`
Run Code Online (Sandbox Code Playgroud)
添加Send和Sync并编译。你可以做:
trait Factory: Send + Sync {
...
}
Run Code Online (Sandbox Code Playgroud)
或者,我的偏好是在静态地图中专门要求它们,因为那是需要它们的地方:
static ITEMS: Lazy<BTreeMap<&'static str, Arc<dyn Factory + Send + Sync>>> =
Lazy::new(|| {
let mut map = BTreeMap::new();
let value = Arc::new(MyCustomFactory) as Arc<dyn Factory + Send + Sync>;
map.insert("foo", value);
map
});
Run Code Online (Sandbox Code Playgroud)
您还可以通过让它推断第二个来减少重复Arc:
let value = Arc::new(MyCustomFactory) as Arc<_>;
Run Code Online (Sandbox Code Playgroud)