rust - 如何根据泛型类型参数给出不同的值?
问题描述
我正在尝试按照openGL 上的 TheChernoProject SeriesVertexBufferLayout
来实现一个结构。我已经很容易地将 C++ 系列改编为 Rust,但我被卡住了。
VertexBufferElement
有一个计数,它使用的 glEnumdata_type
和一个标准化的布尔值。有一个称为通用方法的方法push
,它采用 u32 计数,将 VertexBufferElement 推送到元素 Vec 并更新步幅。
我似乎无法让函数接受匹配类型的代码。我尝试使用TypeId
,Any
和PhantomData
当我遇到错误时。
pub fn push<T: 'a>(&mut self, count: u32) {
let dt = TypeId::of::<T>();
let (data_type, normalized) = if dt == TypeId::of::<i8>() {
(gl::BYTE, false)
} else if dt == TypeId::of::<u8>() {
(gl::UNSIGNED_BYTE, true)
} else if dt == TypeId::of::<i16>() {
(gl::SHORT, false)
} else if dt == TypeId::of::<u16>() {
(gl::UNSIGNED_SHORT, false)
} else if dt == TypeId::of::<i32>() {
(gl::INT, false)
} else if dt == TypeId::of::<u32>() {
(gl::UNSIGNED_INT, false)
} else if dt == TypeId::of::<f16>() {
(gl::HALF_FLOAT, false)
} else if dt == TypeId::of::<f32>() {
(gl::FLOAT, false)
} else if dt == TypeId::of::<f64>() {
(gl::DOUBLE, false)
} else {
panic!("Incompatible Type")
};
self.elements.push(VertexBufferElement{data_type, count, normalized, _marker: PhantomData});
self.stride += mem::size_of::<T>();
}
error[E0310]: the parameter type `T` may not live long enough
--> opengl\examples\vertex_buffer_layout.rs:26:18
|
25 | pub fn push<T: 'a>(&mut self, count: u32) {
| -- help: consider adding an explicit lifetime bound `T: 'static`...
26 | let dt = TypeId::of::<T>();
| ^^^^^^^^^^^^^^^
|
note: ...so that the type `T` will meet its required lifetime bounds
--> opengl\examples\vertex_buffer_layout.rs:26:18
|
26 | let dt = TypeId::of::<T>();
|
起初它是 'T' 可能活得不够长,但它只是一个通用函数,并且浮点数只指示保存的数字,而不是类型本身,所以我尝试了PhantomData
. 之后的任何错误都是我不知道自己在做什么,以前从未使用PhantomData
过,也找不到适合这种情况的任何东西。
解决方案
做编译器建议的事情对我来说很好:
帮助:考虑添加一个明确的生命周期限制
T: 'static
......
use std::any::TypeId;
enum Type {
Byte,
Short,
}
fn decide<T: 'static>() -> (Type, bool) {
let dt = TypeId::of::<T>();
if dt == TypeId::of::<u8>() {
(Type::Byte, false)
} else if dt == TypeId::of::<u16>() {
(Type::Short, true)
} else {
panic!("Unknown type")
}
}
fn main() {}
在 Rust 的未来版本中,您可以使用match
表达式来缩短它:
#![feature(const_type_id)]
fn decide<T: 'static>() -> (Type, bool) {
const ID_U8: TypeId = TypeId::of::<u8>();
const ID_U16: TypeId = TypeId::of::<u16>();
match TypeId::of::<T>() {
ID_U8 => (Type::Byte, false),
ID_U16 => (Type::Short, true),
_ => panic!("Unknown type"),
}
}
我宁愿不允许运行时失败,但是:
enum Type {
Byte,
Short,
}
trait AsType {
fn as_type() -> (Type, bool);
}
impl AsType for u8 {
fn as_type() -> (Type, bool) {
(Type::Byte, false)
}
}
impl AsType for u16 {
fn as_type() -> (Type, bool) {
(Type::Short, true)
}
}
fn main() {
u8::as_type(); // Ok
bool::as_type(); // Error
}
error[E0599]: no function or associated item named `as_type` found for type `bool` in the current scope
--> src/main.rs:24:5
|
24 | bool::as_type();
| ^^^^^^^^^^^^^ function or associated item not found in `bool`
|
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `as_type`, perhaps you need to implement it:
candidate #1: `AsType`
推荐阅读
- python - 拟合峰以减去基线
- javascript - 单击按钮后将注意力集中在 textarea 上
- kubernetes - 如何在 istio 中添加 consul 注册表
- php - Ziparchive 始终包含父目录
- .net - 无法访问 Docker 中的 Couchbase memcached 存储桶
- reactjs - 我们可以在 reactJS 应用程序中使用数据表 jquery 而不是使用 react-data-table-component - 包
- java - 如何在 Flyway 中进行部分迁移以进行测试?
- c++ - _CRTDBG_MAP_ALLOC 不显示文件名和行号
- css - 文本大小和字体颜色的 CSS 调整
- java - log4j 在控制台中仅打印 FATAL 和 ERROR 消息,但不显示 INFO/TRACE