Как дать разные значения на основе параметра общего типа? - PullRequest
0 голосов
/ 29 мая 2018

Я пытаюсь реализовать структуру VertexBufferLayout, следуя TheChernoProject Series на openGL .Я достаточно легко адаптировал серию C ++ к Rust, но я застрял.

VertexBufferElement имеет счетчик, glEnum для data_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>();
}

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', возможно, не жил достаточно долго, но это была только общая функция, и float диктовал только сохраненное число, а не сам тип, поэтому я попытался PhantomData.После любых ошибок я не имел ни малейшего представления о том, что делаю, никогда раньше не использовал PhantomData и не могу ничего найти для этой ситуации.

1 Ответ

0 голосов
/ 29 мая 2018

Выполнение того, что предлагает компилятор, прекрасно работает для меня:

help: рассмотрите возможность добавления явной границы времени жизни 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`
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...