以伪示例的形式:
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
{}
我已经找到了一些方法来绕过这一点,但我想用一种方法来处理语言功能。
在我的项目中,一个小型光线跟踪器,我有一个具有位置和法线的顶点类型。我有另一个顶点类型,包括位置,法线和纹理坐标。
我也有一些适用于特定顶点类型的材质类型。
我想对一些使用顶点和材料的函数进行约束:
fn do_something<V, M>(/* some arguments */)
-> /* some returned value */
where
if V: VertexWithTextureCoordinate
then M: MaterialWithTexture
else if V: SimpleVertex
then M: SimpleMaterial,
{
}
这是我面临的最简单的条件。
答案 0 :(得分:3)
这不容易。首先:在Rust中不存在负性状边界(说不特征Foo
)。有一些RFC,但AFAIK没有具体计划在不久的将来实施类似的东西。但是,专业化可以使您模拟负面特征界限。
Rust的类型系统是Turing完成的,但据我所知,如果不使用专门化和负特征边界,这两个都没有实现/不稳定,那么你想要的确切是不可能的。
你要求的是一个相当普遍的情况;有一些具体情况可能会发生。如果你有这个结构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,
{
// ...
}
如果您考虑一下,无论如何都必须编写两个实现:当T
为A
时,您可以在A
的对象上使用T
的方法,当T
为C
时,您可以在C
的对象上使用T
的方法,但您不能只告诉编译器“A
或{ {1}}”。
在你的情况下,我会创建另一个特征,表示顶点和材料的组合,它们可以很好地协同工作。类似的东西:
C
如您所见,我为顶点和材质的一对(元组)实现了特征。因此,您的功能将如下所示:
trait VertexMaterialPair {
// ...
}
impl<V, M> VertexMaterialPair for (V, M)
where
V: VertexWithTextureCoordinate,
M: MaterialWithTexture,
{ /* ... */ }
impl<V, M> VertexMaterialPair for (V, M)
where
V: SimpleVertex,
M: SimpleMaterial,
{ /* ... */ }
这应该运作得相当好;但是,它可能不是您的光线追踪器的最佳解决方案......