繁体   English   中英

在另一个特征的特征实现中使用 const generic 会导致“不受约束的 const 参数”错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM