簡體   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