簡體   English   中英

Rust:從具有特征綁定的泛型轉換影響特征 object 類型

[英]Rust: conversion from generic with trait bound affects trait object type

我正在 rust 中開發一個簡單的 opengl 包裝器庫。

我使用nalgebra_glm crate 進行數學運算。 許多類型實現AsRef以訪問底層數組。 我為匹配常見矩陣大小的數組類型手動實現了Uniform ,例如[[T; 4]; 4] [[T; 4]; 4] [[T; 4]; 4] , [T; 16] [T; 16] , [T; 3] [T; 3]等等。

所以我可以通過調用Box::new(<nalgebra_glm matrix or vector>.as_ref().clone())獲得一個新的Box<dyn Uniform>但它不必要地冗長。

我想創建一個方便的 function 將任何&[T] CloneAsRef轉換為實現Uniform的某種類型UVec<Box<dyn Uniform>> 類似於ToOwned特征的東西。

這是我想出的。

pub trait Uniform {
    fn bind(&self, location: GLint);
}
pub fn to_owned<U: Uniform + Clone, T: AsRef<U>>(uniforms: &[T]) -> Vec<Box<dyn Uniform>>
where Vec<Box<dyn Uniform>>: FromIterator<Box<U>>
{
    uniforms.into_iter()
        .map(AsRef::as_ref)
        .map(Clone::clone)
        .map(Box::new)
        .collect()
}

但是當我嘗試在以下上下文中使用這個 function 時,它導致了我很難理解的錯誤。

perspective_matrix()view_matrix()都是Mat4類型並提供AsRef<[[f32; 4]; 4] AsRef<[[f32; 4]; 4] AsRef<[[f32; 4]; 4]

let common_uniforms = to_owned(&[camera.perspective_matrix(), camera.view_matrix()]);
error[E0277]: the trait bound `(dyn Uniform + 'static): Clone` is not satisfied
   --> src\main.rs:167:27
    |
167 |     let common_uniforms = to_owned(&[camera.perspective_matrix(), camera.view_matrix()]);
    |                           ^^^^^^^^ the trait `Clone` is not implemented for `(dyn Uniform + 'static)`
    |
note: required by a bound in `uniform::to_owned`
   --> src\uniform.rs:9:30
    |
9   | pub fn to_owned<U: Uniform + Clone, T: AsRef<U>>(uniforms: &[T]) -> Vec<Box<dyn Uniform>>
    |                              ^^^^^ required by this bound in `uniform::to_owned`

為什么生成的特征 object 需要Clone 僅在對通用U進行操作期間才需要clone ,因此只有U應實現Clone 為什么它與最終特征 object 有任何關系? 我希望由於U實現了Uniform ,所以應該可以從中創建一個動態dyn Uniform特征 object。

此外,我不能要求Clone作為Uniform的超級特征,因為它會使 object 不安全。

我已經嘗試將結果框類型顯式轉換為特征 object,添加'static生命周期綁定但無濟於事。

pub fn to_owned<U: 'static + Uniform + Clone, T: AsRef<U>>(uniforms: &[T]) -> Vec<Box<dyn Uniform>>
where Vec<Box<dyn Uniform>>: FromIterator<Box<U>>
{
    uniforms.into_iter()
        .map(AsRef::as_ref)
        .map(Clone::clone)
        .map(|uniform| Box::new(uniform) as Box<dyn Uniform>)
        .collect()
}

我真的不明白我的代碼有什么問題。 要么是我犯了一些句法錯誤,要么是我在這里試圖完成的事情存在更深層次的邏輯錯誤。

我將不勝感激任何幫助。

主要問題是您的to_owned function。

使用where Vec<Box<dyn Uniform>>: FromIterator<Box<U>>你實際上隱藏了真正的問題,導致非常混亂的編譯器消息。

您添加它可能是因為編譯器建議它。 但是編譯器也警告說,雖然這是它所需要的,但添加where子句可能不是正確的解決方案。 使用where子句,而不是指定使轉換成為可能的正確界限,您只需將問題移出 function。我同意編譯器,這是錯誤的解決方案。

您的第二次嘗試幾乎是正確的,您所缺少的只是您需要刪除where子句:

use nalgebra_glm::Mat4;

fn perspective_matrix() -> Mat4 {
    todo!()
}

pub trait Uniform {
    fn bind(&self, location: i32);
}

impl Uniform for [[f32; 4]; 4] {
    fn bind(&self, _location: i32) {
        todo!()
    }
}

pub fn to_owned<T, U>(uniforms: &[T]) -> Vec<Box<dyn Uniform>>
where
    T: AsRef<U>,
    U: Uniform + Clone + 'static,
{
    uniforms
        .into_iter()
        .map(AsRef::as_ref)
        .map(Clone::clone)
        .map(|uniform| Box::new(uniform) as Box<dyn Uniform>)
        .collect()
}

fn main() {
    let _common_uniforms = to_owned(&[perspective_matrix()]);
}

此外,這是一個最小的可重現示例的樣子;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM