2014-12-12 15 views
6

Mam struct Vec3<T>, jak mogę wdrożyć następującą metodę?Dzielenie const przez generic w Rust

impl<T: num::Num + num::Float> Not<Vec3<T>> for Vec3<T> { 
    fn not(&self) -> Vec3<T> { 
     *self * (1.0/(*self % *self).sqrt()) 
    } 
} 

błąd: niedopasowane typy: Oczekuje _, uznał T (oczekiwane jest zmienna zmiennoprzecinkowa, znaleziono parametru typ)

Rodzaj 1.0 jest _ natomiast typ (*self % *self).sqrt() jest T. I wydaje się, że nie można podzielić _ przez T.

próbowałem różnych odlewania do 1,0:

*self * ((1.0 as T)/(*self % *self).sqrt()) 

błędu: non-skalarne obsada: _ jak T

*self * (1.0.div((*self % *self).sqrt())) 

błąd: niedopasowane typy: oczekiwano &_, znaleziono T (oczekiwano & -ptr, znaleziono typ parametru)

Jaki jest najmilszy sposób wdrożenia tej metody?

Edit 1: Zgodnie z życzeniem, tutaj jest moje pełny kod:

use std::num::Float; 

pub struct Vec3<T> { 
    pub x: T, 
    pub y: T, 
    pub z: T, 
} 

impl<T> Vec3<T> { 
    pub fn new(x: T, y: T, z: T) -> Vec3<T> { 
     Vec3 { x: x, y: y, z: z } 
    } 
} 

impl<T: Float> Add<T, Vec3<T>> for Vec3<T> { 
    fn add(&self, rhs: &T) -> Vec3<T> { 
     Vec3 { x: self.x + *rhs, y: self.y + *rhs, z: self.z + *rhs } 
    } 
} 

impl<T: Float> Add<Vec3<T>, Vec3<T>> for Vec3<T> { 
    fn add(&self, rhs: &Vec3<T>) -> Vec3<T> { 
     Vec3 { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z } 
    } 
} 

impl<T: Float> Mul<T, Vec3<T>> for Vec3<T> { 
    fn mul(&self, rhs: &T) -> Vec3<T> { 
     Vec3 { x: self.x * *rhs, y: self.y * *rhs, z: self.z * *rhs } 
    } 
} 

// x % y : dot-product 
impl<T: Float> Rem<Vec3<T>, T> for Vec3<T> { 
    fn rem(&self, rhs: &Vec3<T>) -> T { 
     self.x + rhs.x * self.y + rhs.y * self.z + rhs.z 
    } 
} 

// x^y : cross-product 
impl<T: Float> BitXor<Vec3<T>, Vec3<T>> for Vec3<T> { 
    fn bitxor(&self, rhs: &Vec3<T>) -> Vec3<T> { 
     Vec3 { x: self.y * rhs.z - self.z * rhs.y, 
       y: self.z * rhs.x - self.x * rhs.z, 
       z: self.x * rhs.y - self.y * rhs.x } 
    } 
} 

// !x : Norm 
impl Not<Vec3<f32>> for Vec3<f32> { 
    fn not(&self) -> Vec3<f32> { 
     *self * (1.0f32/(*self % *self).sqrt()) 
    } 
} 

impl Not<Vec3<f64>> for Vec3<f64> { 
    fn not(&self) -> Vec3<f64> { 
     *self * (1.0f64/(*self % *self).sqrt()) 
    } 
} 

użyłbym Num zamiast Float aby móc mieć wektory całkowitą, ale ponieważ jest przestarzałe, myślę, że lepszą opcją jest użycie makra do duplikowania kodu dla wszystkich typów. Powielam tutaj Not dla f32 i f64

Odpowiedz

4

Literały mogą być tylko typów pierwotnych. Nie można rzucić literału do jakiegoś rodzaju ogólnego.

Dla stałych jak 1.0 można użyć metod, takich jak Float::one(), więc Konkretnym przykładem może być przepisany jako

impl<T: num::Float> Not<Vec3<T>> for Vec3<T> { 
    fn not(&self) -> Vec3<T> { 
     *self * (num::Float::one()/(*self % *self).sqrt()) 
    } 
} 

(zauważ, że usunąłem Num związana ponieważ jest przestarzała iw tym przypadku jest ona całkowicie zastąpiona przez Float)

aby przekształcić dowolne wartości wystąpień jakiegoś konkretnego typu FloatNumCast::from() można użyć metody:

let x: T = num::NumCast::from(3.14f64); 

Przy okazji może się okazać, że this accepted RFC jest interesująca.

Aktualizacja

Jest prawdopodobne, że nie będzie w stanie realizować Float dla swojej struktury, ponieważ ma wiele metod specyficznych dla gołych pływaków, jak rozmiar mantysy. Sądzę, że będziesz musiał dodać metody takie jak one() i zero() i prawdopodobnie sam odrzuca numery.Wtedy będziesz w stanie napisać

impl<T: num::Float> Not<Vec3<T>> for Vec3<T> { 
    fn not(&self) -> Vec3<T> { 
     *self * (Vec3::one()/(*self % *self).sqrt()) 
    } 
} 
+0

Dzięki, ale mam ten błąd teraz: typ tej wartości musi być znany w tym kontekście – Shengis

+1

Jak rozumiem, na razie, leki generyczne są bardzo ograniczone, a to nie jest będzie lepiej, usuwając std :: num :: Num – Shengis

+0

@ AurélienFusil-Delahaye, czy mógłbyś podać pełny kod? Potrzebuję instancji operacji dla 'Vec3 ', w przeciwnym razie nie mogę skompilować tego szczególnego fragmentu. –