如何在Rust中创建泛型函数向量并调用?
解决Rust泛型函数存入向量并调用的问题
问题根源
你尝试用Vec<fn(&mut impl Write)>存储泛型函数失败,核心原因有两点:
impl Write在函数指针类型中无法直接使用——函数指针要求明确的类型,impl Trait在这里属于语法错误。- 泛型函数
render_task_enter_field<W>会被Rust单态化:每传入一个不同的W类型,编译器都会生成独立的函数实例,这些实例类型不统一,无法直接放入同一个向量。
解决方案:使用Trait Object统一类型
通过闭包+Trait Object的方式,可将不同单态化后的泛型函数适配成统一类型存入向量。
步骤1:构建函数向量
使用Box<dyn Fn(&mut dyn Write)>作为向量元素类型,把泛型函数包裹进闭包,适配成接受&mut dyn Write的调用签名:
use std::io::{self, Write}; use termion::{raw::IntoRawMode, screen::IntoAlternateScreen}; // 你的泛型函数 fn render_task_enter_field<W>(stdout: &mut W) where W: Write, { writeln!(stdout, "Enter task field").unwrap(); } // 可添加更多同类型泛型函数 fn render_task_list<W>(stdout: &mut W) where W: Write, { writeln!(stdout, "Task list").unwrap(); } fn main() -> io::Result<()> { // 构建渲染函数向量 let render_fns: Vec<Box<dyn Fn(&mut dyn Write)>> = vec![ Box::new(|stdout| render_task_enter_field(stdout)), Box::new(|stdout| render_task_list(stdout)), ];
步骤2:传入Termion的Stdout并调用
你用Termion创建的stdout类型(RawTerminal<AlternateScreen<Stdout>>)已实现Write trait,直接将其可变引用传入闭包即可:
// 创建Termion的终端输出 let mut stdout = io::stdout() .into_raw_mode()? .into_alternate_screen()?; // 遍历向量调用所有渲染函数 for render in render_fns { render(&mut stdout); } // 释放stdout以恢复终端正常状态 drop(stdout); Ok(()) }
原理说明
dyn Write是Trait Object,允许接受任何实现了Write的类型的可变引用。- 闭包
|stdout| render_task_enter_field(stdout)会自动处理类型转换:将&mut dyn Write转换为泛型函数需要的具体&mut W(因W实现了Write,Trait Object可向下转换为具体类型)。 Box<dyn Fn(&mut dyn Write)>让不同闭包(对应不同泛型函数实例)能被统一存储在向量中。
内容的提问来源于stack exchange,提问作者Artem Novikov
相关产品推荐
相关产品推荐

