Für eine beliebige Struktur, die Clone
implementiert, würde Ich mag eine einzelne generische Funktion haben, nimmt entweder:Generisches klonbar/beweglichen Parameter als Funktionsargument
- a
&MyStruct
in welchem Fall es kann bedingt durch die geklont werden Funktion - ein
MyStruct
in diesem Fall ist der Klon nicht notwendig ist, da es bewegt werden kann
ich habe implementiert das alleine:
use std::clone::Clone;
#[derive(Debug)]
struct MyStruct {
value: u64,
}
impl Clone for MyStruct {
fn clone(&self) -> Self {
println!("cloning {:?}", self);
MyStruct { value: self.value }
}
}
trait TraitInQuestion<T> {
fn clone_or_no_op(self) -> T;
}
impl TraitInQuestion<MyStruct> for MyStruct {
fn clone_or_no_op(self) -> MyStruct {
self
}
}
impl<'a> TraitInQuestion<MyStruct> for &'a MyStruct {
fn clone_or_no_op(self) -> MyStruct {
self.clone()
}
}
fn test<T: TraitInQuestion<MyStruct>>(t: T) {
let owned = t.clone_or_no_op();
}
fn main() {
let a = MyStruct { value: 8675309 };
println!("borrowing to be cloned");
test(&a);
println!("moving");
test(a);
}
und der Ausgang ist wie erwartet:
borrowing to be cloned
cloning MyStruct { value: 8675309 }
moving
Ist diese Funktionalität schon irgendwie Clone
durch die Implementierung abgeleitet? Wenn nicht, klingt std::borrow::ToOwned
wie das, was ich will, aber ich kann es nicht funktionieren:
use std::clone::Clone;
use std::borrow::Borrow;
#[derive(Debug)]
struct MyStruct {
value: u64,
}
impl Clone for MyStruct {
fn clone(&self) -> Self {
println!("cloning {:?}", self);
MyStruct { value: self.value }
}
}
fn test<T: ToOwned<Owned = MyStruct>>(a: T) {
let owned = a.to_owned();
}
fn main() {
let a = MyStruct { value: 8675309 };
println!("borrowing to be cloned");
test(&a);
println!("moving");
test(a);
}
Compiler Ausgabe:
error[E0277]: the trait bound `MyStruct: std::borrow::Borrow<T>` is not satisfied
--> src/main.rs:16:1
|
16 |/fn test<T: ToOwned<Owned = MyStruct>>(a: T) {
17 | | let owned = a.to_owned();
18 | | }
| |_^ the trait `std::borrow::Borrow<T>` is not implemented for `MyStruct`
|
= help: consider adding a `where MyStruct: std::borrow::Borrow<T>` bound
= note: required by `std::borrow::ToOwned`
Tun, was der Compiler durch test
Wechsel schlägt vor:
fn test<T: ToOwned<Owned = MyStruct>>(a: T) ->()
where
MyStruct: Borrow<T>,
{
let owned = a.to_owned();
}
Und der resultierende Fehler:
error[E0308]: mismatched types
--> src/main.rs:27:10
|
27 | test(&a);
| ^^ expected struct `MyStruct`, found &MyStruct
|
= note: expected type `MyStruct`
found type `&MyStruct`
Wenn ich versuche, ToOwned
für &MyStruct
impl<'a> ToOwned for &'a MyStruct {
type Owned = MyStruct;
fn to_owned(&self) -> Self::Owned {
self.clone()
}
}
ich die folgende Fehlermeldung erhalten zu implementieren:
error[E0119]: conflicting implementations of trait `std::borrow::ToOwned` for type `&MyStruct`:
--> src/main.rs:16:1
|
16 |/impl<'a> ToOwned for &'a MyStruct {
17 | | type Owned = MyStruct;
18 | |
19 | | fn to_owned(&self) -> Self::Owned {
20 | | self.clone()
21 | | }
22 | | }
| |_^
|
= note: conflicting implementation in crate `alloc`
Sind Sie Kennen Sie schon Kuh? – Shepmaster
In hohem Grade verwandt: [Gibt es eine Weise, eine Funktion zu schreiben, die eine Referenz, eine Bewegung oder eine Umwandlung annimmt, die nur Eigenschaften von der Standardbibliothek verwendet?] (Https://stackoverflow.com/q/47225805/155423) – Shepmaster
Oh Ich war mir nicht bewusst, Kuh. Das ist ziemlich genau das, was ich gesucht habe, muss es verpasst haben. Obwohl es in einigen Fällen unnötig erscheint, eine Eingabe in eine Enum zu schreiben (d. H. "Cow" ist eine dynamische Ausgabe, da meine "TraitInQuestion" eine statische Ausgabe ist, wenn diese Analogie sinnvoll ist) – 10101