2016-11-01 3 views
2

Ich versuche, eine Struktur in Rust zu erstellen, die selbst generisch in Bezug auf andere generische Strukturen ist. Das ist ziemlich verwirrend so hoffentlich dieses Beispiel macht die Dinge klarer:Erstellen Sie eine Struktur, die generisch ist über eine andere generische Struktur

use std::ops::Deref; 
use std::rc::Rc; 

struct Foo<T: Deref> { 
    val: T<i32>, 
    other: i32, 
} 

impl<T> Foo<T> { 
    pub fn new(&self, val: T<i32>, other: i32) -> Self { 
     Foo {val: val, other: other} 
    } 
} 

fn main() { 
    let foo = Foo::new(Rc::new(0), 0); 
} 

playground

Ich möchte in der Lage sein, ein Foo Objekt zu erstellen, durch den Aufruf new mit entweder Rc<i32> Objekten oder Arc<i32> Objekte je nachdem, ob ich brauchte Fadensicherheit oder nicht. Ich bekomme den folgenden Fehler, wenn ich dies versuche: error[E0109]: type parameters are not allowed on this type, wie der Compiler über die i32 in val: T<i32>, beschwert. Ist das in Rust möglich? Wenn ja, kann ich sicher Methoden auf i32 aufrufen, vorausgesetzt, es wird es automatisch dereferenzieren?

+1

Im Gegensatz zu einigen anderen Sprachen hat Rust leider (noch) keine höheren Typen, daher müssen Typ-Parameter konkrete Typen sein. In diesem Fall stimme ich @Shepmaster jedoch zu, dass Sie es nicht benötigen. –

Antwort

3

Das Syntax keinen Sinn macht, aber diese Version kompiliert:

use std::ops::Deref; 
use std::rc::Rc; 
use std::sync::Arc; 

struct Foo<T> { 
    val: T, 
    other: i32, 
} 

impl<T> Foo<T> 
    where T: Deref<Target = i32> 
{ 
    pub fn new(val: T, other: i32) -> Self { 
     Foo { 
      val: val, 
      other: other, 
     } 
    } 
} 

fn main() { 
    let foo = Foo::new(Rc::new(0), 0); 
    let foo = Foo::new(Arc::new(0), 0); 
} 

Beachten Sie, wie das Merkmal lesen Grenzen: T: Deref<Target = i32> "Jede T die Deref mit einem Target eines i32 implementiert".

Sie können dann Methoden implementieren, die dereferenzieren val:

fn sum(&self) -> i32 { 
    *self.val + self.other 
} 

Im Allgemeinen ist das Konzept der so etwas wie

struct Foo<T> { 
    val: T<i32>, 
} 

nicht als nützlich erweisen würde. Nur weil etwas über eine i32 parametrisiert ist, bedeutet das nicht, dass Sie tun können irgendetwas mit dem i32. Ebenso könnte ein Typ mit etwas außer einer i32 (oder überhaupt nicht) parametrisiert werden und Ihnen immer noch Zugriff auf eine i32 geben.

+0

Super, danke für die Hilfe! Ich werde es jetzt ausprobieren. Ich würde denken, dass dies eine gebräuchlichere Technik wäre, um schnell eine generische Struktur zu bekommen, die threadsicher sein kann oder nicht abhängig von Ihren Bedürfnissen, sehen Sie das oft? – jeromefroe

Verwandte Themen