[英]using const generic in implementation of trait for another trait causes "unconstrained const parameter" error
我正在尝试实现一些抽象的线性代数特征和结构,作为我学习 rust 实践的一部分。 在下面的代码中,当我为 VectorDynamic< VectorAbstract<TValue>
实现VectorDynamic<TValue>
时没有问题; 但是当我尝试对VectorStatic<TValue, DIM_COUNT>
执行相同操作时,我收到以下错误:
the const parameter `DIM_COUNT` is not constrained by the impl trait, self type, or predicates
unconstrained const parameter
note: expressions using a const parameter must map each value to a distinct output value
note: proving the result of expressions other than the parameter are unique is not supported
我在这里做错了什么?
实现这一点的正确方法是什么?
这是我的代码:
pub trait VectorAbstract<TValue: Scalar>: VectorSpaceElement + // a dozen std traits
{
fn dot(lhs: &Self, rhs: &Self) -> TValue;
}
pub trait VectorDynamic<TValue: Scalar>: VectorAbstract<TValue> {
fn dim_count(&self) -> usize;
fn from_list(arr: Vec<TValue>) -> Self;
}
pub trait VectorStatic<TValue: Scalar, const DIM_COUNT: usize>: VectorAbstract<TValue> {
fn from_array(arr: [TValue; DIM_COUNT]) -> Self;
}
impl<TValue: Scalar, TVector: VectorDynamic<TValue>> VectorAbstract<TValue> for TVector {
fn dot(lhs: &Self, rhs: &Self) -> TValue {
// ... dot product body for dynamic vectors ...
}
}
impl<TValue: Scalar, const DIM_COUNT: usize, TVector: VectorStatic<TValue, DIM_COUNT>>
VectorAbstract<TValue> for TVector
{
fn dot(lhs: &Self, rhs: &Self) -> TValue {
// ... dot product body for static vectors ...
}
}
更新 1
我还尝试了以下方法:
pub trait VectorStatic<TValue: Scalar>: VectorAbstract<TValue> {
const DIM_COUNT: usize;
fn from_array(arr: [TValue; Self::DIM_COUNT]) -> Self;
}
impl<TValue: Scalar, TVector: VectorStatic<TValue>> VectorAbstract<TValue> for TVector {
fn dot(lhs: &Self, rhs: &Self) -> TValue {
// ... dot product body for static vectors ...
}
}
但是我在声明from_array
function 时收到以下错误:
generic parameters may not be used in const operations
cannot perform const operation using `Self`
note: type parameters may not be used in const expressions
注意:我希望在编译时以某种方式获得 DIM_COUNT,因此VectorStatic
没有fn dim_count()
。
更新 2
此外,当我完全删除 VectorStatic 的实现时,我在另一个文件中收到另一个错误,其中我有一个Vector2
结构并尝试为此实现VectorStatic<TValue, 2>
:
pub struct Vector2<TValue: Scalar> {
pub x: TValue,
pub y: TValue,
}
impl<TValue: Scalar> VectorStatic<TValue, 2> for Vector2<TValue> {
// ... implementation ...
}
这是错误:
the trait bound `math::algebra::vectors::vector2::Vector2<TValue>: math::algebra::abstractions::VectorDynamic<TValue>` is not satisfied
the trait `math::algebra::abstractions::VectorDynamic<TValue>` is not implemented for `math::algebra::vectors::vector2::Vector2<TValue>`
请注意,此 Vector2 结构根本不应该是VectorDynamic
。 这里肯定有一些我没有清楚地理解的东西,也许 rust 认为我正在尝试使每个VectorAbstract
都成为VectorDynamic
或类似的东西?
我错过了什么?
更新 3
也许我还应该提到我已经尝试了以下方法:
impl<TValue: Scalar> VectorAbstract<TValue> for dyn VectorDynamic<TValue>
{
fn dot(lhs: &Self, rhs: &Self) -> TValue {
// ... dot product body for dynamic vectors ...
}
}
impl<TValue: Scalar, const DIM_COUNT: usize> VectorAbstract<TValue> for dyn VectorStatic<TValue, DIM_COUNT>
{
fn dot(lhs: &Self, rhs: &Self) -> TValue {
// ... dot product body for static vectors ...
}
}
但在那种情况下,我得到了这两个错误:
the trait `math::algebra::abstractions::VectorDynamic/VectorStatic` cannot be made into an object
然后有十几行说因为他们使用Self
作为类型参数。
您的原始代码的问题在于,不能保证类型TVector
只会实现VectorStatic<TValue, 1>
而不会实现VectorStatic<TValue, 2>
,这会导致VectorAbstract<TValue>
的实现冲突。
更新 1 是 go 的方式,因为这样一个类型不能多次实现VectorStatic
。 目前,这需要每晚lib.rs
并在 lib.rs / main.rs
的开头添加#![feature(generic_const_exprs)]
下一个问题将是VectorAbstract<TValue>
的 2 个impl
-s。 同样,没有什么可以保证TVector
不会同时实现VectorDynamic<TValue>
和VectorStatic<TValue>
,这会导致VectorAbstarct<TValue>
的实现冲突。 据我所知,即使使用不稳定的功能也无法做到这一点。 最好的方法是使用包装结构。
VectorStatic1
+ VectorStaticWrapper1
需要添加的功能,并且仅适用于夜间 rust 版本, VectorStatic2
+ VectorStaticWrapper2
工作稳定。
#![feature(generic_const_exprs)]
pub trait Scalar {}
pub trait VectorAbstract<TValue: Scalar>:
{
fn dot(lhs: &Self, rhs: &Self) -> TValue;
}
pub trait VectorDynamic<TValue: Scalar>: VectorAbstract<TValue> {
fn dim_count(&self) -> usize;
fn from_list(arr: Vec<TValue>) -> Self;
}
pub trait VectorStatic1<TValue: Scalar>: VectorAbstract<TValue> {
const DIM_COUNT: usize;
fn from_array(arr: [TValue; Self::DIM_COUNT]) -> Self;
}
pub trait VectorStatic2<TValue: Scalar, const DIM_COUNT: usize>: VectorAbstract<TValue> {
fn from_array(arr: [TValue; DIM_COUNT]) -> Self;
}
struct VectorDynamicWrapper<T>(T);
struct VectorStaticWrapper1<T>(T);
struct VectorStaticWrapper2<T, const DIM_COUNT: usize>(T);
impl<TValue: Scalar, TVector: VectorDynamic<TValue>> VectorAbstract<TValue> for VectorDynamicWrapper<TVector> {
fn dot(lhs: &Self, rhs: &Self) -> TValue {
let lhs = &lhs.0;
let rhs = &rhs.0;
todo!()
}
}
impl<TValue: Scalar, TVector: VectorStatic1<TValue>>
VectorAbstract<TValue> for VectorStaticWrapper1<TVector>
{
fn dot(lhs: &Self, rhs: &Self) -> TValue {
let lhs = &lhs.0;
let rhs = &rhs.0;
let dim_count = TVector::DIM_COUNT;
todo!()
}
}
impl<TValue: Scalar, const DIM_COUNT: usize, TVector: VectorStatic2<TValue, DIM_COUNT>>
VectorAbstract<TValue> for VectorStaticWrapper2<TVector, DIM_COUNT>
{
fn dot(lhs: &Self, rhs: &Self) -> TValue {
let lhs = &lhs.0;
let rhs = &rhs.0;
todo!()
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.