在Rust中用泛型划分const [英] Dividing a const by a generic in Rust
问题描述
我有一个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 $ 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())
}
}
$ c $ (注意我删除了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屋!