我有一个在数据上工作的特性,它在多个维度上都是有界的,所以我用const泛型创建它,允许我定义这些界限:
trait Transmogrifier<const N: usize, const W: usize, const B: usize> {
// ...
}然后,我还有另外一个特性,它本身使用Transmogrifier,所以我必须创建一个相当不愉快的外观特征:
trait Foo<T: Transmogrifier<N, W, B>, const N: usize, const W: usize, const B: usize> {
fn init(transmogrifier: T) -> Self;
// ...
}我不需要N、W和B在Foo实现中,但是编译器会抱怨如果我没有在其中添加它们,所以meh。
不过,现在我已经确定,我需要扩展Transmogrifier以获得一些辅助特性,这些特性提供了不同的方法来执行一些变形者的操作,这些操作本身使用了一些const泛型来实现自己的目的,这给我留下了一个绝对可怕的演示:
trait Spindler<const N: usize> {
// ...
}
trait Mutilator<const W: usize> {
// ...
}
trait Transmogrifier<S: Spindler<N>, M: Mutilator<W>, const N: usize, const W: usize, const B: usize> {
// ...
}
trait Foo<T: Transmogrifier<S, M, N, W, B>, S: Spindler<N>, M: Mutilator<W>, const N: usize, const W: usize, const B: usize> {
fn init(transmogrifier: T) -> Self;
// ...
}在这一点上,所有的重复和冗长的大写字母列表都让我心烦意乱,我开始认为我犯了一个可怕的设计错误,而且有一种不同的方法。有没有更好的方法来做这件事,这是我还没有找到的语法快捷方式,还是这就是我要做的,而我只需要一瘸一拐地想想克里皮呢?
发布于 2022-09-26 07:23:30
您可以使用简化的代理特性和一揽子实现:
trait TransmogrifierProxy {
// Here go the methods you *actually* need in Foo.
}
impl<S: Spindler<N>, M: Mutilator<W>, const N: usize, const W: usize, const B: usize>
TransmogrifierProxy for Transmogrifier<S, M, N, W, B> {
// Implement methods you need using Transmogrifier...
}然后,Foo简化为:
trait Foo<T: TransmogrifierProxy> {
fn init(transmogrifier: T) -> Self;
// ...
}发布于 2022-09-26 08:46:01
将/指定泛型参数传递/指定给一个特征有多种方法:
现在,你已经选择把每个参数作为一个单一的通用参数来传递--这是一个简单的反射--但是其他5种模式中的任何一种都可能更明智。
泛型参数,或相关项,还是函数参数?
在特征级别上,选择取决于单个类型是否应该为给定参数的1或多个值实现该特性:
在一个特征上有一个通用函数会有不同的结果:它更灵活,但排除了在dyn上下文中使用该特性。
标准库中的示例:
Iterator使用关联的Item类型:有一种类型的元素是由给定的collection.Extend使用产生的:char或str可以附加到String;而不是i32.单参数还是参数束?
如果多个参数链接在一起,那么将它们捆绑在一起可能是有意义的。
例如,最近我用几种方法创建了一个特性,每个方法都被赋予了一个额外的用户定义的参数--用户可以传递他们想要的任何补充数据。我可以将该特性定义为每个方法接受1个泛型参数,但正如您注意到的那样,这很快就变得难以处理了:
trait Foo<A, B, C> {
fn a(&self, x: String, user: A);
fn b(&self, y: i64, user: B);
fn c(&self, z: Option<&str>, user: C);
}
fn fooing<A, B, C>(foo: &impl Foo<A, B, C>);相反,该特性是由单个类型参数化的,它本身实现了一个特性:
trait Fooer {
type A = ();
type B = ();
type C = ();
}
trait Foo<F: Fooer> {
fn a(&self, x: String, user: F::A);
fn b(&self, y: i64, user: F::B);
fn c(&self, z: Option<&str>, user: F::C);
}
fn fooing<F: Fooer>(foo: &impl Foo<F>);用户仍然可以自定义每个方法中传递的额外数据,但是任何操作Foo的操作都会大大减少样板。
https://stackoverflow.com/questions/73850591
复制相似问题