【问题标题】:How to give different values based on a generic type parameter?如何根据泛型类型参数给出不同的值?
【发布时间】:2018-05-29 12:55:20
【问题描述】:

我正在尝试通过遵循TheChernoProject Series on openGL 来实现VertexBufferLayout 结构。我已经很容易地将 C++ 系列改编为 Rust,但我被卡住了。

VertexBufferElement 有一个计数,它使用的data_type 的 glEnum 和一个标准化的布尔值。有一个名为push 的通用方法,它采用 u32 计数,将 VertexBufferElement 推送到元素 Vec 并更新步幅。

我似乎无法让函数接受匹配类型的代码。当我遇到错误时,我尝试使用TypeIdAnyPhantomData

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>();
}

vertex_buffer_layout.rs

    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,并且找不到任何适合这种情况的东西。

【问题讨论】:

    标签: rust


    【解决方案1】:

    按照编译器的建议去做对我来说很好:

    帮助:考虑添加明确的生命周期绑定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`
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-22
      • 1970-01-01
      • 2019-08-17
      • 2013-11-30
      相关资源
      最近更新 更多