2015-05-17 3 views
2

В Русте, в &T, где T является trait является жиром ссылки, которые на самом деле соответствует raw::TraitObject:Как получить v-ptr для данной комбинации Trait/Struct?

pub struct TraitObject { 
    pub data: *mut(), 
    pub vtable: *mut(), 
} 

Используя TraitObject, можно отменить конструкцию и вновь построить &T на досуге.

Однако, в то время как получение vtable от де-построения &T легко, что если я не имею &T в первую очередь, но только T и S; по существу, что-то вроде:

fn make_vptr<T: ?Sized, S>() -> *mut(); 

Как я могу бояться v-ptr оттуда? Есть ли какие-либо внутренние свойства, которые я мог бы использовать?

Примечание: наивная реализация создания S (или заклинания его из воздуха), а затем создание ссылки &T не работает; компилятор жалуется, что T необязательно является trait и поэтому &T является либо одним указателем, либо двумя указателями в размере.

ответ

3

возможность заключается в том, чтобы использовать макрос, чтобы сделать волшебную работу:

#![feature(core)] 

macro_rules! make_vptr(
    ($S:ty, $T:ty) => (
     { 
      let s: &$S = unsafe { ::std::mem::uninitialized() }; 
      let t: &$T = s; 
      let r: ::std::raw::TraitObject = unsafe { ::std::mem::transmute(t) }; 
      r.vtable 
     } 
    ) 
); 

Этот код не будет компилироваться, если T не черта (благодаря transmute(..) проверки, что &T является жир указатель) или если T не выполняется S (благодаря заданию).

Затем он может быть использован непосредственно:

use std::fmt::Display; 

fn main() { 
    let u32_display_vtable = make_vptr!(u32, Display); 

    let x = 42u32; 

    let disp: &Display = unsafe { ::std::mem::transmute(
     ::std::raw::TraitObject { 
      data: &x as *const _ as *mut _, 
      vtable: u32_display_vtable 
     } 
    ) }; 

    println!("{}", disp); 
} 
+0

Не как общий (к сожалению), поскольку он не может быть вызван в рамках общей функции, но этого должно быть достаточно для моей цели. Благодаря! –

0

Я не верю, что в настоящее время это возможно.

Для того, чтобы это сработало, вам нужно будет ограничить общий параметр T только признавать черты. Вы не можете этого сделать. В результате он никогда не позволит вам что-либо делать с &T, который зависит от того, что он является признаком, например, для получения vtable.

+0

То есть именно то, что блокирует меня, да. –