*const () 可以替代泛型,更加灵活。下面举了两个完全不一样的数据结构Foo和Bar;以及不同的函数,来说明。
一、 代码
trait Work {
fn process(&self);
}
struct Foo(String);
impl Work for Foo {
fn process(&self) {
println!("process work from Foo : {}", self.0);
}
}
struct Bar{
code:String,
open:f64,
high:f64,
low:f64,
close:f64,
}
impl Bar{
fn new(code:String,open:f64,high:f64,low:f64,close:f64)->Self{
Self{
code,
open,
high,
low,
close,
}
}
}
impl Work for Bar {
fn process(&self) {
println!("process work from Bar : {}", self.code);
}
}
fn fn_foo(foo: &Foo){
println!("call fn_foo, output ->{}", foo.0);
}
fn fn_bar(bar: &Bar){
println!("call fn_bar, output ->code:{} open:{} high:{} close:{} low:{},", bar.code,bar.open,bar.high,bar.close,bar.low);
}
fn main() {
let foo = Foo("foo".into());
let bar = Bar::new("600036.SH".into(),36.9,37.8,36.7,36.4);
let unsafe_fn_foo: unsafe fn(*const ()) = fn_const_ptr(fn_foo as fn(&Foo));
process_method::<Foo>( unsafe_fn_foo,&foo);
let unsafe_fn_bar: unsafe fn(*const ()) = fn_const_ptr(fn_bar as fn(&Bar));
process_method::<Bar>(unsafe_fn_bar,&bar);
let foo_ptr: *const () = data_const_ptr(&foo);
let bar_ptr: *const () = data_const_ptr(&bar);
process_data::<Foo>(foo_ptr);
process_data::<Bar>(bar_ptr);
}
fn process_data<T: Work>(data: *const ()) {
let obj: *const T = data.cast::<T>();
unsafe{(*obj).process()};
}
fn process_method<T>(f: unsafe fn(*const ()),data:&T) {
let ptr: *const () = data as *const T as _; // 这里"_"是 type erase
unsafe{
f(ptr)
};
}
fn data_const_ptr<T>(data: &T) -> *const () {
data as *const T as _ // 这里"_"是 type erase
}
fn fn_const_ptr<T>(f: fn(&T)) -> unsafe fn(*const ()) {
unsafe {
std::mem::transmute(f)
}
}
二、输出结果
Compiling type_erase v0.1.0 (D:\my_program\type_erase)
Finished `release` profile [optimized] target(s) in 2.08s
Running `target\release\type_erase.exe`
call fn_foo, output ->foo
call fn_bar, output ->code:600036.SH open:36.9 high:37.8 close:36.4 low:36.7,
process work from Foo : foo
process work from Bar : 600036.SH