有没有办法结合多个特征(通过继承?)来定义一个新的特征?我正在寻找像C++中的概念:
auto concept newConcept<typename T> : concept1<T>, concept2<T>, concept3<T> {};
Run Code Online (Sandbox Code Playgroud)
假设我想创建一个继承自的新特征Clone,Default以及其他一些特征,那可能吗?
在查看 Rust 结构体的文档时,我经常会遇到标题为“Blanket Implements”的部分。我听说它可以用来实现所有类型或匹配某些条件的所有类型的特征,但我不确定为什么需要这样做。
那么一揽子实现到底是什么?为什么它们在 Rust 中有用?
是否可以使用指定的关联类型创建特征别名?我正在使用类似问题的方法为多个特征输入别名
trait Trait {
type Item;
}
fn print<T>(value: T) where T: Trait<Item=char> {
}
trait Alias: Trait {}
impl<T: Trait<Item=char>> Alias for T {}
fn print_alias<T: Alias>(value: T) {
print(value)
}
fn main() {
}
Run Code Online (Sandbox Code Playgroud)
但是无法编译并出现以下错误:
<anon>:12:5: 12:10 error: type mismatch resolving `<T as Trait>::Item == char`:
expected associated type,
found char [E0271]
<anon>:12 print(value)
^~~~~
<anon>:12:5: 12:10 note: required by `print`
<anon>:12 print(value)
^~~~~
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)
围栏链接:http://is.gd/LE4h6a
我的目标是打印具有特征对象成员的结构的内容,但我找不到如何告诉 Rust 编译器该成员还实现了其他特征,例如Displayor Debug。
例如,在下面的程序中,我想打印 的结构S2(并S1进行比较),但我陷入了 的实现中fmt。
trait Tr {}
impl Tr for usize {}
impl Tr for String {}
#[derive(Debug)]
struct S1<A: Tr + std::fmt::Debug> {
member: Box<A>,
}
struct S2 {
member: Box<Tr>,
}
impl std::fmt::Debug for S2 {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
// ??
Ok(())
}
}
fn main() {
let s1 = S1 {
member: Box::new(String::from("abc")),
};
println!("{:?}", s1);
let s2 = …Run Code Online (Sandbox Code Playgroud) 根据这个问题和这个回答的问题,不可能简单地定义一个特征别名,如:
trait Alias = Foo + Bar;
Run Code Online (Sandbox Code Playgroud)
解决方法有点难看:
trait Alias : Foo + Bar {}
impl<T: Foo + Bar> Alias for T {}
Run Code Online (Sandbox Code Playgroud)
因此,我想为此定义一个宏.我试过了
macro_rules! trait_alias {
( $name : ident, $base : expr ) => {
trait $name : $base {}
impl<T: $base> $name for T {}
};
}
trait Foo {}
trait Bar {}
trait_alias!(Alias, Foo + Bar);
Run Code Online (Sandbox Code Playgroud)
但它失败了,错误:
src\main.rs:5:17: 5:22 error: expected one of `?`, `where`, or `{`, found `Foo + Bar`
src\main.rs:5 …Run Code Online (Sandbox Code Playgroud) 我想创建一个抽象特征,它指定索引类型和值类型,其中实现该特征的任何结构都必须实现Index<IndexType>并IndexMut<IndexType>定义Output在实现该特征的每个结构中保持相同的类型。
我尝试创建一个特征,但似乎无法指定输出类型:
use std::ops::{Index, IndexMut};
struct Coord;
struct LightValue;
trait LightMap: Index<Coord> + IndexMut<Coord> {}
impl LightMap {
type Output = LightValue;
}
Run Code Online (Sandbox Code Playgroud)
warning: trait objects without an explicit `dyn` are deprecated
--> src/lib.rs:8:6
|
8 | impl LightMap {
| ^^^^^^^^ help: use `dyn`: `dyn LightMap`
|
= note: `#[warn(bare_trait_objects)]` on by default
error[E0191]: the value of the associated type `Output` (from the trait `std::ops::Index`) must be specified
--> src/lib.rs:8:6
|
8 | …Run Code Online (Sandbox Code Playgroud) 现有语法允许我们为关联类型编写默认值:
trait Foo {
type Bar = i32;
}
Run Code Online (Sandbox Code Playgroud)
我想要类似 C++ 的东西:
trait Foo {
typedef int Bar;
}
Run Code Online (Sandbox Code Playgroud)
这不是有效的 Rust 代码,但试图表明我的意图:
trait Foo<T> {
trait Trait = Into<T> + /* 10 other traits dependent on T */;
fn foo(x: Type) -> Trait;
}
Run Code Online (Sandbox Code Playgroud) 在库中,人们可能希望根据功能标志将特征的实现限制为线程安全。这有时涉及改变特质继承。但是,特征继承边界上不允许使用属性。常见的解决方法是复制特征:
#[cfg(not(feature = "thread_safe"))]
pub trait MyTrait {
fn foo();
}
#[cfg(feature = "thread_safe")]
pub trait MyTrait: Send + Sync {
fn foo();
}
Run Code Online (Sandbox Code Playgroud)
可以通过使用宏来减少重复的代码(见下文),但这可能会影响 IDE 体验。有没有更好的方法来实现条件性状遗传?
macro_rules! my_trait {
($($bounds:ident),*) => {
pub trait MyTrait where $(Self: $bounds),* {
fn foo();
}
};
}
#[cfg(not(feature = "thread_safe"))]
my_trait!();
#[cfg(feature = "thread_safe")]
my_trait!(Send, Sync);
Run Code Online (Sandbox Code Playgroud) 我学到了一个习语,为 Trait 起一个别名。但是,当我将这个习惯用法应用到我的代码中时,我遇到了一个令人费解的错误。
这是代码的简化版本:
// `StrToStr` is an alias for `Fn(&str) -> &str`
trait StrToStr: Fn(&str) -> &str {}
impl<T> StrToStr for T where T: Fn(&str) -> &str {}
// A function that returns `StrToStr`
fn identity() -> impl StrToStr {
|s: &str| s
}
Run Code Online (Sandbox Code Playgroud)
当我编译此代码时,出现以下错误:
error[E0308]: mismatched types
--> src/main.rs:77:18
|
77 | fn identity() -> impl StrToStr {
| ^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected reference `&str`
found reference …Run Code Online (Sandbox Code Playgroud) AsyncWrite我有一个实现和 的自定义套接字AsyncRead。我想将 dyn 存储到该套接字,但我想同时使用两者AsyncWrite/Read,如下所示:
#[derive(Clone)]
pub struct AsyncTransporter {
stream: Arc<dyn AsyncRead + AsyncWrite>,
}
Run Code Online (Sandbox Code Playgroud)
但这不受支持。
60 | stream: Arc<dyn AsyncRead + AsyncWrite>,
| --------- ^^^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: tokio::io::AsyncRead + tokio::io::AsyncWrite {}`
Run Code Online (Sandbox Code Playgroud)
如果我这样做trait NewTrait: tokio::io::AsyncRead + tokio::io::AsyncWrite {},这两个特征的方法将如何实现?