[英]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]
Clone
和AsRef
轉換為實現Uniform
的某種類型U
到Vec<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.