在Rust中用泛型划分const [英] Dividing a const by a generic in Rust

查看:259
本文介绍了在Rust中用泛型划分const的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个struct Vec3< T> ,我该如何实现以下方法?

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

错误:不匹配类型:预期 _ ,找到 T (预期的浮点变量,找到的类型参数)



1.0的类型是<$ (* self%* self).sqrt()的类型为 T 时,c $ c> _ C $ C>。而且它似乎不能用T分割一个__。

我试着用各种各样的方式输入1.0:

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


$ b $

错误:非标量转换: _ 作为 T

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

错误:不匹配的类型:预计& _ ,找到 T (expected& -ptr,找到的类型参数)

是实现这种方法的最好方法吗?



编辑1:
根据要求,这是我的完整代码:

 使用std :: num :: Float; 

pub结构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>添加< T,Vec3< T>>对于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>添加< Vec3< T>,Vec3< T>对于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>对于Vec3< T> {
fn mul(& self,rhs:& T) - > VEC3< T> {
Vec3 {x:self.x * * rhs,y:self.y * * rhs,z:self.z * * rhs}
}
}

// x%y:点积
impl< T:Float> Rem< Vec3< T>,T>对于Vec3< T> (& self,rhs:& Vec3< T>) - > {
fn rem T {
self.x + rhs.x * self.y + rhs.y * self.z + rhs.z
}
}

// x ^ y:交叉产品
impl< T:Float> BitXor< Vec3< T>,Vec3< T>对于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:标准
impl不是< Vec3< F32>>对于Vec3< f32> {
fn not(& self) - > VEC3< F32> {
* self *(1.0f32 /(* self%* self).sqrt())
}
}

impl不是< Vec3< f64>>> ;对于Vec3< f64> {
fn not(& self) - > VEC3< F64> {
* self *(1.0f64 /(* self%* self).sqrt())
}
}

我会用 Num 而不是 Float 来能够有整数向量,但由于它已被弃用,我认为更好的选择是使用宏来复制所有类型的代码。在这里,我重复不是为 f32 f64

解决方案

文字只能是原始类型。对于像 1.0 这样的常量,你可以使用类似于的方法, a href =http://doc.rust-lang.org/std/num/trait.Float.html#tymethod.one =nofollow> Float :: one() code> ,因此您的具体示例可以重写为:

  impl< T:num :: Float> ;不< VEC3< T>>对于Vec3< T> {
fn not(& self) - > VEC3< T> {
* self *(num :: Float :: one()/(* self%* self).sqrt())
}
}
Num
bound,因为它已被弃用,在这种情况下它是完全被 Float 所取代)

将任意值转换为某些特定< Float 类型,您可以使用 NumCast :: from() 方法:

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

顺便说一句,您可能会发现这个被接受的RFC 有趣。

更新



您的结构很可能无法实现 Float ,因为它有许多专用于裸浮游物的方法,像尾数大小。我想你将不得不添加诸如 one() zero()之类的方法,并且可能会自己从数字中转换。然后你就可以写出:

pre $ impl< T:num :: Float>不< VEC3< T>>对于Vec3< T> {
fn not(& self) - > VEC3< T> {
* self *(Vec3 :: one()/(* self%* self).sqrt())
}
}


I have a struct Vec3<T>, how can I implement the following method ?

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

error: mismatched types: expected _, found T (expected floating-point variable, found type parameter)

Type of 1.0 is _ while type of (*self % *self).sqrt() is T. And it seems it can't divide a _ by a T.

I tried various casting for 1.0 :

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

error: non-scalar cast: _ as T

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

error: mismatched types: expected &_, found T (expected &-ptr, found type parameter)

What is the sleekest way to implement this method ?

Edit 1: As requested, here is my full code :

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())
    }
}

I would have used Num instead of Float to be able to have integer vectors, but since it's deprecated, I think the better option is to use macro to duplicate code for all types. Here I duplicated Not for f32 and f64

解决方案

Literals can only be of primitive types. You can't cast a literal to some generic type.

For constants like 1.0 you can use methods like Float::one(), so your specific example could be rewritten as

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

(note that I removed Num bound because it is deprecated and in this case it is entirely superseded by Float)

To convert arbitrary values to instances of some specific Float type you can use NumCast::from() method:

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

BTW, you may find this accepted RFC interesting.

Update

It is likely that you won't be able to implement Float for your structure because it has a lot of methods specific to bare floats, like mantissa size. I guess you will have to add methods like one() and zero() and probably casts from numbers yourself. Then you will be able to write

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

这篇关于在Rust中用泛型划分const的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆