![](/img/trans.png)
[英]Mismatched types parameter error on rust generics
[英]Mismatched types when using associated consts and const generics in Rust nightly
因此,對於我正在編寫的庫,我想計算 N 維(2、3、4 等...)中兩點之間的距離,並且我有一個 Point 特征,以便庫的用戶可以在他們的自己的類型,只要它們是“點像”。
我有一個特征“Point”,它的維度 (N) 和浮點類型 (T) 保持為關聯類型和常量:
pub trait Point: Copy + Clone {
type T: num::Float;
const N: usize;
fn as_array(&self) -> [Self::T; Self::N];
}
以及使用它的函數:
fn dist<P>(a: &P, b: &P) -> P::T
where
P: Point,
[(); P::N]: ,
{
// implementation goes here ...
}
按預期使用 Point 特征的示例:
#[derive(Copy, Clone)]
struct MyCustomPoint { a: f64, b: f64 }
impl Point for MyCustomPoint {
type T = f64;
const N: usize = 2;
fn as_array(&self) -> [Self::T; Self::N] {
[self.a, self.b]
}
}
問題
如果我為 [f32;N] 實現 Point trait,我會遇到以下問題:
error[E0308]: mismatched types
--> src\main.rs:63:9
|
63 | *self
| ^^^^^ expected `Self::N`, found `N`
|
= note: expected type `Self::N`
found type `N`
導致問題的代碼:
impl<const N: usize> Point for [f32; N] {
type T = f32;
const N: usize = N;
fn as_array(&self) -> [Self::T; Self::N] {
*self
}
}
當在代碼中使用數字時,為什么下面的代碼會導致類型不匹配錯誤?
impl Point for [f32; 3] {
type T = f32;
const N: usize = 3;
fn as_array(&self) -> [Self::T; Self::N] {
*self
}
}
所有代碼放在一個塊中:
#![feature(adt_const_params)]
#![feature(generic_const_exprs)]
use num::Float;
pub trait Point: Copy + Clone {
type T: num::Float;
const N: usize;
fn as_array(&self) -> [Self::T; Self::N];
}
fn dist<P>(a: &P, b: &P) -> P::T
where
P: Point,
[(); P::N]: ,
{
let mut dist_sq: P::T = num::zero();
for i in 0..P::N {
let delta = (a.as_array())[i] - (b.as_array())[i];
dist_sq = dist_sq + delta * delta;
}
dist_sq.sqrt()
}
// Works
#[derive(Copy, Clone)]
struct MyCustomPoint { a: f64, b: f64 }
impl Point for MyCustomPoint {
type T = f64;
const N: usize = 2;
fn as_array(&self) -> [Self::T; Self::N] {
[self.a, self.b]
}
}
// Works
// impl Point for [f32; 3] {
// type T = f32;
// const N: usize = 3;
// fn as_array(&self) -> [Self::T; Self::N] {
// *self
// }
// }
// Doesn't work
impl<const N: usize> Point for [f32; N] {
type T = f32;
const N: usize = N;
fn as_array(&self) -> [Self::T; Self::N] {
*self
}
}
fn main() {
let a = [0f32, 1f32, 0f32];
let b = [3f32, 1f32, 4f32];
assert_eq!(dist(&a, &b), 5f32);
}
另外,我發現以下是一種解決方法。
fn as_array(&self) -> [Self::T; Self::N] {
// *self
// Workaround - replace with something simpler if possible.
let mut array = [0f64; Self::N];
array[..Self::N].copy_from_slice(&self[..Self::N]);
array
}
只使用穩定的 Rust,我相信你可以實現你想要的。 假設您想要的效果只是能夠在任意(但相同)維度的數組上調用dist()
或具有相同通用參數值並從.as_array()
返回相同大小數組的 Point 對象.
將.as_array()
方法添加到所有浮點值數組,遵循一個共同的模式,即聲明一個特征以追溯地向現有類型添加特征。
use num::Float;
pub trait Point<T: Float, const N: usize>: Copy + Clone {
fn as_array(&self) -> [T; N];
}
impl<T: Float, const N: usize> Point<T, N> for [T; N] {
fn as_array(&self) -> [T; N] {
*self
}
}
然后是一個函數,它采用正確的泛型組合供編譯器根據其參數進行定制。
fn dist<P, T, const N: usize>(a: &P, b: &P) -> T
where
P: Point<T, N>,
T: Float,
{
let mut dist_sq: T = num::zero();
for i in 0..N {
let delta = (a.as_array())[i] - (b.as_array())[i];
dist_sq = dist_sq + delta * delta;
}
dist_sq.sqrt()
}
這使代碼如下:
fn main() {
let a = [0f32, 1f32, 0f32];
let b = [3f32, 1f32, 4f32];
assert_eq!(dist(&a, &b), 5f32);
println!("dist(&a, &b): {}", dist(&a, &b));
let c = [1f64, 2f64, 3f64, 4f64, 5f64];
let d = [6f64, 7f64, 8f64, 9f64, 10f64];
println!("dist(&c, &d): {}", dist(&c, &d));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.