首页 > 解决方案 > fn 的可选泛型类型参数?

问题描述

我想要一个函数有一个可选的泛型类型参数来做这样的事情:

fn main() {
    bar::<()>();
}

fn bar<F: Foo>() {
    let x = some_computation();
    if F != () {
        let foo = F::new(x);
        foo.foo();
    }
}

trait Foo {
    fn new(x: u64) -> Self;
    fn foo(&self);
}

有没有办法有一个可选的类型参数?如果是这样,有没有办法检查类型参数是否存在于函数中?

我想答案是否定的,但是有可能用宏来做到这一点吗?

标签: genericsrusttype-parameter

解决方案


通常,您不能为函数指定默认类型参数,也无法区分类型参数,除非通过 trait 上的方法。

最简单的解决方法是只使用两个函数,例如barand bar_with,其中一个不接受类型参数,另一个接受一个类型参数:

// call with no type parameters
pub fn bar() {
    let x = some_computation();
}

// call with type parameter
pub fn bar_with<F: Foo>() {
    let x = some_computation();

    let foo = F::new(x);
    foo.foo();
}

如果函数足够复杂,您可以拥有两个函数都调用的私有辅助函数:

// call with no type parameters
pub fn bar() {
    bar_inner(|_x| { /* do nothing */ })
}

// call with type parameter
pub fn bar_with<F: Foo>() {
    bar_inner(|x| {
        let foo = Foo::new(x);
        foo.foo();
    })
}

fn bar_inner<Func: FnOnce(u64)>(func: Func) {
    let x = some_computation();
    func(x);
}

或者,您可以使用为所有类型实现的附加特征Foo和默认类型 ( ()) 来解决此问题:

trait BarArg {
    fn bar_inner(x: u64);
}

impl<F: Foo> BarArg for F {
    fn bar_inner(x: u64) {
        let foo = foo::new(x);
        foo.foo();
    }
}

impl BarArg for () {
    fn bar_inner(_x: u64) {
        // do nothing
    }
}

fn bar<B: BarArg>() {
    let x = some_computation();
    B::bar_inner(x)
}

推荐阅读