以下代码使用具有泛型类型的结构.虽然它的实现仅对给定的特征边界有效,但可以使用或不使用相同的边界来定义结构.struct的字段是私有的,因此无论如何其他代码都无法创建实例.
trait Trait {
fn foo(&self);
}
struct Object<T: Trait> {
value: T,
}
impl<T: Trait> Object<T> {
fn bar(object: Object<T>) {
object.value.foo();
}
}
Run Code Online (Sandbox Code Playgroud)
是否应该忽略对结构有约束力的特性以符合DRY原则,还是应该给予澄清依赖性?或者是否存在一种解决方案应优先于另一种解决方案?
我有一个包含函数对象的结构:
struct Foo<F> {
func: F,
}
Run Code Online (Sandbox Code Playgroud)
我想添加Fn绑定到结构定义的特征.问题是:我确实关心第一个参数(必须是i32),而不是第二个参数.我真正想写的是这样的:
struct Foo<F>
where
? P so that F: Fn(i32, P),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
所以在英语中:类型F必须是一个带有两个参数的函数,第一个是i32(和第二个可以是任何东西).上面的语法显然无效.我想到了三个可能的解决方案:
该for<>语法不会帮助这里.除了它对非寿命参数不起作用的事实之外,它是通用的("为所有人")而不是存在的("存在").所以那就是了.
另一种可能性是向结构添加类型参数.我已经不喜欢那个解决方案了,因为参数本身并不属于struct.
struct Foo<F, P>
where
F: Fn(i32, P),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
但是这不起作用:P除了where绑定之外没有使用参数,所以编译器会抱怨.
这个问题可以通过添加一个PhantomData<P>字段来解决,但这不是必需的,更重要的是,用户不能再轻易使用struct constructor语法了.
最后我试过这个:
struct Foo<F>
where
F: Fn(i32, _),
{
func: F,
}
Run Code Online (Sandbox Code Playgroud)
但这也行不通:
error[E0121]: the type placeholder `_` is not allowed within types on item signatures …Run Code Online (Sandbox Code Playgroud)假设我想创建一些包含其他泛型类型的类型,如下所示:
struct MyWrapper<T> {
pub inner: T,
}
Run Code Online (Sandbox Code Playgroud)
现在我希望我的类型有一个方法,如果内部类型满足特定的绑定.例如:我想打印它(在这个例子中没有使用fmt特征来简化).为此,我有两种可能性:向impl方法本身添加绑定.
impl<T> MyWrapper<T> {
pub fn print_inner(&self) where T: std::fmt::Display {
println!("[[ {} ]]", self.inner);
}
}
Run Code Online (Sandbox Code Playgroud)
当MyWrapper<()>我得到一个调用此函数时:
error[E0277]: `()` doesn't implement `std::fmt::Display`
--> src/main.rs:20:7
|
20 | w.print_inner();
| ^^^^^^^^^^^ `()` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string
|
= help: the trait `std::fmt::Display` is not implemented for `()`
Run Code Online (Sandbox Code Playgroud)
impl<T: std::fmt::Display> …Run Code Online (Sandbox Code Playgroud) 我有一个看起来像这样的特征:
trait Handler<C> {
fn handle(&self, msg: &Message, connection: &mut C);
}
Run Code Online (Sandbox Code Playgroud)
实例应该像链接HTTP处理程序的中间件一样被链接:
let handler = FirstHandler {
next: SecondHandler {
next: FinalHandler {},
},
};
Run Code Online (Sandbox Code Playgroud)
每种处理程序类型都可以对类型施加额外的约束C:
trait ConnectionThatWorksWithFirstHandler {
...
}
struct FirstHandler<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> {
next: H,
_phantom: PhantomData<C>,
}
Run Code Online (Sandbox Code Playgroud)
正如你在这里看到的,我需要一个PhantomData<C>避免错误E0392(parameter C is never used).但是,PhantomData在语义上是错误的,因为处理程序没有持有实例C.这很难看.例如,我手动必须提供正确的同步/发送特征实现:
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Send for Handler<C, H> where H: Send {}
unsafe impl<C: ConnectionThatWorksWithFirstHandler, H: Handler<C>> Sync for Handler<C, H> where H: …Run Code Online (Sandbox Code Playgroud) 在 Rust 1.15 中,我创建了一个特征来抽象读取和解析文件格式。我正在尝试创建一个内部具有此通用特征的结构。
我有这个特点:
use std::io::Read;
trait MyReader<R: Read> {
fn new(R) -> Self;
fn into_inner(self) -> R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个结构,它引用了实现这个的东西。
struct MyIterThing<'a, T: MyReader<R>+'a> {
inner: &'a mut T,
}
Run Code Online (Sandbox Code Playgroud)
给出以下错误:
use std::io::Read;
trait MyReader<R: Read> {
fn new(R) -> Self;
fn into_inner(self) -> R;
fn get_next(&mut self) -> Option<u32>;
fn do_thingie(&mut self);
}
Run Code Online (Sandbox Code Playgroud)
T: MyReader+'a, 我收到错误: "error[E0243]: wrong number of type arguments: expected 1, found 0",T: MyReader<R: …