2016-07-04 4 views
4
struct Vector { 
    data: [f32; 2] 
} 

impl Vector { 
    //many methods 
} 

今度はNormalを作成したいと思いますが、ほぼVectorのように動作しますが、タイプを区別する必要があります。たとえば、法線を変換することはベクトルを変換することとは異なります。たとえば、トランジションされた(逆の)行列で変換する必要があります。Rustの機能を共有するには?

今、私はこのようにそれを行うことができます:

struct Normal { 
    v: Vector 
} 

そして私は、私はまた、その後PhantomData

struct VectorType; 
struct NormalType; 
struct PointType; 
struct Vector<T = VectorType> { 
    data: [f32; 2], 
    _type: PhantomData<T>, 
} 
type Normal = Vector<NormalType>; 

でそれを行うしかし、と思うすべての機能

impl Normal { 
    fn dot(self, other: Normal) -> f32 { 
     Vector::dot(self.v, other.v) 
    } 
    .... 
} 

を再実装特定のタイプの機能を実装する方法も必要です。

を追加することができるように、すべての場合にはaddのように実装するのは簡単です。

それとも何らかの形

impl Vector<NormalType> {..} // Normal specific stuff 

私はサブレンジのための機能を実装する方法を確認しない固有の機能を提供します。例えば、ドットプロダクトは法線とベクトルだけに意味があり、点は意味を成さないかもしれません。

特性境界のブール表現を表現することは可能ですか?

trait NormalTrait; 
trait VectorTrait; 
impl NormalTrait for NormalType {} 
impl VectorTrait for VectorType {} 

impl<T: PointTrait or VectorTrait> for Vector<T> { 
    fn dot(self, other: Vector<T>) -> f32 {..} 
} 

私の選択肢には何がありますか?

答えて

3

あなたの質問はかなり広く、多くのトピックに触れています。しかし、あなたのPhantomDataアイデアは良い解決策になるかもしれません。さまざまなジェネリックタイプに異なるimplブロックを書くことができます。私はあなたのコードにいくつかのことを追加しました:

struct VectorType; 
struct NormalType; 
struct PointType; 
struct Vector<T = VectorType> { 
    data: [f32; 2], 
    _type: PhantomData<T>, 
} 
type Normal = Vector<NormalType>; 
type Point = Vector<PointType>; 

// --- above this line is old code -------------------- 

trait Pointy {} 
impl Pointy for VectorType {} 
impl Pointy for PointType {} 

// implement for all vector types 
impl<T> Vector<T> { 
    fn new() -> Self { 
     Vector { 
      data: [0.0, 0.0], 
      _type: PhantomData, 
     } 
    } 
} 

// impl for 'pointy' vector types 
impl<T: Pointy> Vector<T> { 
    fn add<R>(&mut self, other: Vector<R>) {} 
    fn transform(&mut self) { /* standard matrix multiplication */ } 
} 

// impl for normals 
impl Vector<NormalType> { 
    fn transform(&mut self) { /* tranposed inversed matrix stuff */ } 
} 

fn main() { 
    let mut n = Normal::new(); 
    let mut p = Point::new(); 
    n.transform(); 
    p.transform(); 

    // n.add(Normal::new()); // ERROR: 
    // no method named `add` found for type `Vector<NormalType>` in the current scope 
    p.add(Point::new()); 
} 

は、形質境界のための論理式を表現することが可能ですか?

いいえ(まだ)。しかし、あなたは上のようにこのケースでそれを解決することができます:新しい形質(Pointy)を作成し、あなたの "または"条件の型に対してそれを実装します。それからあなたはその特性に縛られました。

+1

「PhantomData 」の必要はありません。単に 'T 'と置き換えてください。 – Shepmaster

+0

(私は思う)。バイトオーダーの仕方のようなもの。 – Shepmaster

+0

特性境界にブール式のRFCがありますか? –

関連する問題