提问人:Cecile 提问时间:11/9/2023 更新时间:11/9/2023 访问量:58
如何在 Rust 中调用从 trait 继承的方法
How to call an inherited method from trait in Rust
问:
pub mod stuff {
pub trait Clone2: Clone {}
impl<T: Clone> Clone2 for Vec<T> {}
}
fn main() {
let x: Vec<u32> = Default::default();
let _ = stuff::Clone2::clone(&x);
}
我想从特征中调用 but 的方法,但由于某种原因它没有编译。有一些注意事项:.clone()
Clone
Clone2
- 我不想简单地这样做,因为我不一定在范围内(也不一定会有事件克隆)。
x.clone()
Clone2
- 我不想使用,因为我需要确保该类型实际实现。
Clone::clone(&x)
Clone2
Compiling playground v0.0.1 (/playground)
error[E0782]: trait objects must include the `dyn` keyword
--> src/main.rs:9:13
|
9 | let _ = stuff::Clone2::clone(&x);
| ^^^^^^^^^^^^^
|
help: add `dyn` keyword before this trait
|
9 | let _ = <dyn stuff::Clone2>::clone(&x);
| ++++ +
error[E0038]: the trait `Clone2` cannot be made into an object
--> src/main.rs:9:34
|
9 | let _ = stuff::Clone2::clone(&x);
| ^^ `Clone2` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:2:23
|
2 | pub trait Clone2: Clone {}
| ------ ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
= note: required for the cast from `&Vec<u32>` to `&dyn Clone2`
error[E0277]: the size for values of type `dyn Clone2` cannot be known at compilation time
--> src/main.rs:9:34
|
9 | let _ = stuff::Clone2::clone(&x);
| -------------------- ^^ doesn't have a size known at compile-time
| |
| required by a bound introduced by this call
|
= help: the trait `Sized` is not implemented for `dyn Clone2`
note: required by a bound in `clone`
--> /rustc/cc66ad468955717ab92600c770da8c1601a4ff33/library/core/src/clone.rs:160:5
error[E0038]: the trait `Clone2` cannot be made into an object
--> src/main.rs:9:13
|
9 | let _ = stuff::Clone2::clone(&x);
| ^^^^^^^^^^^^^ `Clone2` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:2:23
|
2 | pub trait Clone2: Clone {}
| ------ ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
error[E0038]: the trait `Clone2` cannot be made into an object
--> src/main.rs:9:13
|
9 | let _ = stuff::Clone2::clone(&x);
| ^^^^^^^^^^^^^^^^^^^^^^^^ `Clone2` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:2:23
|
2 | pub trait Clone2: Clone {}
| ------ ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
error[E0746]: return type cannot have an unboxed trait object
--> src/main.rs:9:13
|
9 | let _ = stuff::Clone2::clone(&x);
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
help: box the return type, and wrap all of the returned values in `Box::new`
|
9 | let _ = Box<stuff::Clone2::clone>(&x);
| ++++ +
Some errors have detailed explanations: E0038, E0277, E0746, E0782.
For more information about an error, try `rustc --explain E0038`.
error: could not compile `playground` (bin "playground") due to 6 previous errors
现在我发现唯一有效的方法是:
pub mod stuff {
pub trait Clone2: Clone {}
impl<T: Clone> Clone2 for Vec<T> {}
}
fn main() {
let x: Vec<u32> = Default::default();
fn clone2_clone<T: stuff::Clone2>(x: &T) -> T {
x.clone()
}
let _ = clone2_clone(&x);
}
这很好,但我真的希望在不定义新功能的情况下这样做。
答:
2赞
Cecile
11/9/2023
#1
最后,我认为我发现的最好的解决方案是复制(没有双关语)他们对该特征所做的事情。core::mem::copy()
Copy
https://doc.rust-lang.org/std/mem/fn.copy.html
按位复制值。
这个功能不是魔术;从字面上看,它被定义为
pub fn copy<T: Copy>(x: &T) -> T { *x }
当您想要将函数指针传递给组合器而不是定义新的闭包时,它很有用。
例:
#![feature(mem_copy_fn)] use core::mem::copy; let result_from_ffi_function: Result<(), &i32> = Err(&1); let result_copied: Result<(), i32> = result_from_ffi_function.map_err(copy);
由于我使用的是 trait,因此我将函数作为“提供的方法”放在 trait 中:
pub mod stuff {
pub trait Clone2: Clone {
fn clone2(&self) -> Self {
Clone::clone(self)
}
}
impl<T: Clone> Clone2 for Vec<T> {}
}
fn main() {
let x: Vec<u32> = Default::default();
stuff::Clone2::clone2(&x);
}
评论
Clone2
clone
<Clone2 as Clone>::clone()
clone()
Clone
Clone2
Clone2
clone2()
Clone2
clone()