You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust结构体中保存参数未指定的函数指针并调用?

在Rust中实现支持任意参数函数的通用容器

你想要的是一个能容纳任意函数、并通过元组参数调用它的通用结构,类似C++中传递未严格指定参数的函数指针的场景。Rust作为静态类型语言,无法直接使用无类型指定的函数指针,但可以通过自定义trait结合泛型来实现类似的效果——你的思路方向是对的,但原代码中的FN_TRAIT和std::marker::Tuple无法直接使用,以下是可行的实现方案:

核心实现思路

定义一个抽象函数调用行为的trait,为不同参数数量的函数实现该trait,让容器可以通过统一的接口调用任意符合要求的函数。由于Rust不支持可变参数的trait实现,我们可以用宏批量生成不同参数数量的trait实现,减少重复代码。

完整代码示例

// 定义抽象函数调用的trait
pub trait Callable {
    type Output;
    fn call(&self, args: impl IntoArgs<Self>) -> Self::Output;
}

// 定义将元组转换为函数参数的辅助trait
pub trait IntoArgs<C: Callable> {
    fn into_args(self, func: &C) -> C::Output;
}

// 用宏批量实现不同参数数量的Callable和IntoArgs
macro_rules! impl_callable {
    ($($arg:ident),*) => {
        impl<F, R, $($arg),*> Callable for F
        where
            F: Fn($($arg),*) -> R,
        {
            type Output = R;
            fn call(&self, args: impl IntoArgs<Self>) -> R {
                args.into_args(self)
            }
        }

        impl<F, R, $($arg),*> IntoArgs<F> for ($($arg),*)
        where
            F: Fn($($arg),*) -> R,
        {
            fn into_args(self, func: &F) -> R {
                func($(self.$arg),*)
            }
        }
    };
}

// 实现0到3个参数的情况,可根据需求扩展更多
impl_callable!();
impl_callable!(A);
impl_callable!(A, B);
impl_callable!(A, B, C);

// 通用函数容器
struct Cont<F: Callable> {
    func: F,
}

impl<F: Callable> Cont<F> {
    fn new(func: F) -> Self {
        Self { func }
    }

    fn start(&self, args: impl IntoArgs<F>) -> F::Output {
        self.func.call(args)
    }
}

// 测试函数
fn temp(a: i32, b: i32) {
    println!("{}", a + b);
}

fn hello() {
    println!("Hello, Rust!");
}

fn main() {
    let add_cont = Cont::new(temp);
    add_cont.start((0, 1)); // 输出: 1

    let hello_cont = Cont::new(hello);
    hello_cont.start(()); // 输出: Hello, Rust!
}

关键说明

  1. 为什么不能直接用std::marker::Tuple:Tuple只是一个标记trait,仅用于标记类型是元组,没有任何方法,也不满足对象安全要求,无法作为dyn trait类型传递。我们需要用泛型元组类型来匹配函数的参数列表。
  2. 宏的作用:Rust的trait无法直接支持可变参数,因此用宏批量生成不同参数数量的trait实现,覆盖常见的函数参数场景,你可以根据需求扩展更多参数数量的实现。
  3. 类型安全:整个实现仍然保持Rust的静态类型安全,编译期会检查传递的元组参数是否与函数的参数类型匹配,避免运行时错误。

内容的提问来源于stack exchange,提问作者Michael Smoliar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 15:17:43