Generics 有没有办法在泛型类型上设置复杂的条件和约束?

Generics 有没有办法在泛型类型上设置复杂的条件和约束?,generics,rust,constraints,generic-programming,Generics,Rust,Constraints,Generic Programming,以伪示例的形式: trait A {} trait B {} trait C {} struct D<T, X> where if T: A then X: is not B else if X: B then T: C {} trait A{} 性状B{} 性状C{} 结构D 哪里 如果T:A 那么X:不是B吗 否则,如果X:B 然后T:C {} 我已经找到了一些绕过这一点的方法,但我想要一种使用语言特性的方法 更多解释 在我的

以伪示例的形式:

trait A {}
trait B {}
trait C {}
struct D<T, X>
where
    if T: A 
        then X: is not B
    else if X: B
        then T: C
{}
trait A{}
性状B{}
性状C{}
结构D
哪里
如果T:A
那么X:不是B吗
否则,如果X:B
然后T:C
{}
我已经找到了一些绕过这一点的方法,但我想要一种使用语言特性的方法

更多解释 在我的项目,一个小型光线跟踪器中,我有一个顶点类型,它有一个位置和一个法线。我有另一个顶点类型,有位置、法线和纹理坐标

我也有一些材质类型,可以处理特定的顶点类型

我想对一些同时使用顶点和材质的函数进行约束:

fn do_something<V, M>(/* some arguments */) 
    -> /* some returned value */ 
where 
    if V: VertexWithTextureCoordinate 
        then M: MaterialWithTexture 
    else if V: SimpleVertex
        then M: SimpleMaterial,
{
}
fn做某事(/*一些参数*/)
->/*某些返回值*/
哪里
如果V:带纹理坐标的顶点
然后M:材质有纹理
否则如果V:SimpleVertex
M:简单材料,
{
}

这是我面临的最简单的情况。

这不是那么容易做到的。首先:在Rust中还不存在负的特质界限(比如说nottrait
Foo
)。有一些RFC,但在不久的将来没有具体的计划来实施类似的东西。然而,专业化可以让你模拟消极的特质界限

Rust的类型系统是图灵完备的,但据我所知,如果不使用专门化和负特征边界,就不可能精确实现您想要的,这两种边界都是不实现/不稳定的

你所要求的是一个相当普遍的情况;在某些特定情况下,这是可能的。如果您有这个结构
D
,并且希望向其中添加需要这些特征边界的方法,那么您可以只编写两个
impl
块:

impl<T, X> D<T, X>
where
    T: A,
    X: NotB, // assume `NotB` is just another trait
{   
    // ...
}

impl<T, X> D<T, X>
where 
    T: C,
    X: B,
{
    // ...
}
如您所见,我实现了顶点和材质对(元组)的特征。因此,您的函数如下所示:

fn do_something<V, M>(/* some arguments */) -> /* ... */ 
where
    (V, M): VertexMaterialPair,
{ /* ... */ }
fn做某事(/*一些参数*/)->/*…*/
哪里
(V,M):垂直材料空气,
{ /* ... */ }

这应该可以做得比较好,;但是,它可能不是光线跟踪器的最佳解决方案

你能解释一下你为什么想要这样的条件吗?通常,如果您约束类型参数,那么impl可以使用traits的方法;如果只使用重叠子集,则使用条件时,实现只能进行类型检查。然而,最近被接受的[Specialization RFC]()将有效地使至少一些条件成为可能。
fn do_something<V, M>(/* some arguments */) -> /* ... */ 
where
    (V, M): VertexMaterialPair,
{ /* ... */ }