我正在嘗試實作一些抽象的線性代數特征和結構,作為我學習 Rust 實踐的一部分。在當我執行下面的代碼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函式時收到以下錯誤:
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,所以沒有fn dim_count()for VectorStatic.
更新 2
Also when I completely remove the implementation for VectorStatic, I get another error in another file where I have a Vector2 struct and try to implement VectorStatic<TValue, 2> for that:
pub struct Vector2<TValue: Scalar> {
pub x: TValue,
pub y: TValue,
}
impl<TValue: Scalar> VectorStatic<TValue, 2> for Vector2<TValue> {
// ... implementation ...
}
And here's the error :
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>`
Note that this Vector2 struct is not supposed to be a VectorDynamic at all.
There's definitely something I have not understood clearly here, maybe rust thinks I'm trying to make every VectorAbstract a VectorDynamic or something like that ?
What is it that I'm missing ?
UPDATE 3
Perhaps I should also mention that I already tried the following :
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 ...
}
}
But in that case I get this error for both :
the trait `math::algebra::abstractions::VectorDynamic/VectorStatic` cannot be made into an object
and then a dozen lines that say because they used Self as a type parameter.
uj5u.com熱心網友回復:
您的原始代碼的問題在于,不能保證型別TVector只會實作VectorStatic<TValue, 1>而不是實作VectorStatic<TValue, 2>會產生沖突的VectorAbstract<TValue>.
更新 1 是要走的路,因為這樣一個型別不能實作VectorStatic多次。目前這需要每晚生銹,#![feature(generic_const_exprs)]并在lib.rs/開始時添加main.rs
接下來的問題將是2impl的-s VectorAbstract<TValue>。同樣,沒有什么可以保證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!()
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/370271.html
上一篇:泛型和在運行時選擇正確的介面實作
