Generics 泛型在锈病中的部分特化

Generics 泛型在锈病中的部分特化,generics,rust,Generics,Rust,让我们看一些数学向量的例子。它由不同数量的构件组成,具体取决于空间尺寸 对于2D:x,y 对于三维:x,y,z 对于4D:x,y,z,w 通用:N个组件 在C++中,我可以使用sFIEAE概念来实现它。 模板 结构向量; //用于2D的工具 模板 结构向量 { tx; T y; } //用于3D的工具 模板 结构向量 { tx; T y; tz; } //4D工具 模板 结构向量 { tx; T y; tz; TW; } 如何在Rust中实现同样的功能?如果做不到这一点,元组类型在这里可能

让我们看一些数学向量的例子。它由不同数量的构件组成,具体取决于空间尺寸

  • 对于2D:x,y
  • 对于三维:x,y,z
  • 对于4D:x,y,z,w
  • 通用:N个组件
在C++中,我可以使用sFIEAE概念来实现它。
模板
结构向量;
//用于2D的工具
模板
结构向量
{
tx;
T y;
}
//用于3D的工具
模板
结构向量
{
tx;
T y;
tz;
}
//4D工具
模板
结构向量
{
tx;
T y;
tz;
TW;
}

如何在Rust中实现同样的功能?

如果做不到这一点,元组类型在这里可能会很方便。您可以在下面定义generic
Vector
struct,其目的是将元组类型作为generic-type参数:

struct Vector<T> {
   pub coord: T,
}

impl<T> Vector<T> {
   fn new(coord: T) -> Self {
      Self { coord }
   }
}
类似地,对于三维(即,
T=(f32、f32、f32)
):

类型V3d=向量;
让v3d=v3d::new((1.0,2.0,3.0));

不能用C++中的锈式专业模板专门化泛型。(Rust有一个称为“专门化”的特性,但它只适用于
impl
s,在这里它并不真正相关。)Rust泛型有时被称为“有原则的”,因为它们必须在原则上工作(在声明时),而不仅仅是在实践中(一旦实例化)。这是RIST设计者避免C++中SfIEAE的一些复杂后果的<>强> < /P> 我可以考虑两种主要方法来实现对C++中的C++代码的类似效果,这取决于代码的一般上下文。一种方法是使用一种特性作为类型级函数来计算参数化结构的内容类型,它类似于C++版本,但是略微有点冗长的字段访问(为了简单起见,我将设想<代码> T <代码>这些代码示例为<代码> f32 < /代码>):

现在,您可以编写适用于
Vector
的通用函数,并使用
x
y
,但要使其适应以允许变异并不容易。一种方法是添加
x_mut
y_mut
z_mut
返回
&mut f32
的方法

相关问题

我们并没有真正的防锈剂。C++模板实际上是一种伪装成泛型的代码生成机制,而…基本上任何其他语言都是参数多态性的类型系统机制。一些对Rust有更多经验的人可能会出现,并找到一种方法将其整合在一起,但Rust的惯用方法肯定是使用不同的结构(
Vector2
Vector3
Vector4
),然后将任何常见功能放在一个trait中(
trait Vector{…
),我非常失望。我认为锈支持ScEAE,像C++。非常感谢你如此详细的回答,你帮了我很多。
let v2d /* : Vector<(f32,f32)> */ = Vector::new((1.0, 2.0)); value

println!("v2 = ({}, {})", v2d.coord.0, v2d.coord.1);
type V3d = Vector<(f32, f32, f32)>;

let v3d = V3d::new((1.0, 2.0, 3.0));
// types that contain the actual data
struct Vector2 {
    x: f32,
    y: f32,
}

struct Vector3 {
    x: f32,
    y: f32,
    z: f32,
}

// types that will be used to parameterize a type constructor
struct Fixed<const N: usize>;
struct Dynamic;

// a type level function that says what kind of data corresponds to what type
trait VectorSize {
    type Data;
}

impl VectorSize for Fixed<2> {
    type Data = Vector2;
}

impl VectorSize for Fixed<3> {
    type Data = Vector3;
}

impl VectorSize for Dynamic {
    type Data = Vec<f32>;
}

// pulling it all together
struct Vector<Z>(Z::Data) where Z: VectorSize;
struct Vector<const N: usize> {
    xs: [f32; N],
}

impl<const N: usize> Vector<N> {
    fn x(&self) -> f32 where Self: SizeAtLeast<2> {
        self.xs[0]
    }

    fn y(&self) -> f32 where Self: SizeAtLeast<2> {
        self.xs[1]
    }
    
    fn z(&self) -> f32 where Self: SizeAtLeast<3> {
        self.xs[2]
    }
}

// In current Rust, you can't bound on properties of const generics, so you have
// to do something like this where you implement the trait for every relevant
// number. Macros can make this less tedious. In the future you should be able to
// simply add bounds on `N` to `x`, `y` and `z`.
trait SizeAtLeast<const N: usize> {}

impl SizeAtLeast<2> for Vector<2> {}
impl SizeAtLeast<2> for Vector<3> {}
impl SizeAtLeast<2> for Vector<4> {}

impl SizeAtLeast<3> for Vector<3> {}
impl SizeAtLeast<3> for Vector<4> {}