有没有办法在使用 Option::None 时提示编译器使用某种默认泛型类型?

2023-11-27

我需要一个函数来获取Option属于泛型类型T实现该特质std::iter::IntoIterator。 一个幼稚的实现可能如下所示(是的,展开会出现恐慌None):

fn main() {
    let v = vec![1i32, 2, 3];
    print_iter(Some(v));
    print_iter(None);
}

fn print_iter<T: IntoIterator<Item = i32>>(v: Option<T>) {
    for e in v.unwrap() {
        println!("{}", e);
    }
}

Test on 操场.

这按预期工作Some(...),但失败了None with:

error[E0282]: type annotations needed
 --> src/main.rs:4:5
  |
4 |     print_iter(None);
  |     ^^^^^^^^^^ cannot infer type for `T`

显然类型是T在这些情况下是未知的。一个可以使用print_iter::<Vec<i32>>(None);但这并不感觉很惯用,因为这给出了一些不基于任何内容的任意类型......

有什么方法可以向编译器暗示我不关心None或者使用某种默认值?


有什么方法可以向编译器暗示我不关心None或者使用某种默认值?

您可以实现自己的非通用值作为默认值。首先,我们假设print_iter不接受Option<T>,但是它自己的枚举:

enum PrintArg<T> {
    Ignore,
    Use(T),
}

fn print_iter<T: IntoIterator<Item = i32>>(v: PrintArg<T>) {
    if let PrintArg::Use(v) = v {
        for e in v {
            println!("{}", e);
        }
    }
}

这还没有解决问题,因为如果你通过了PrintArg::Ignore to print_iter(),您回到了第一个方 - 编译器无法推断出T。但用你自己的类型,你可以轻松改变print_iter接受任何可能的事情转换的 into PrintArg:

fn print_iter<T, V>(v: T)
where
    T: Into<PrintArg<V>>,
    V: IntoIterator<Item = i32>,
{
    if let PrintArg::Use(v) = v.into() {
        for e in v {
            println!("{}", e);
        }
    }
}

通过此修改,您可以创建一个虚拟的非泛型Ignore重视并使用From特征来定义其转换为PrintArg::Ignore<T> with T您的选择 - 例如:

struct Ignore;

impl From<Ignore> for PrintArg<Vec<i32>> {
    fn from(_v: Ignore) -> Self {
        PrintArg::Ignore
    }
}

As Ignore是非通用的,它的使用不需要(或接受)<T>。虽然我们确实必须发明一种类型PrintArg<T> in the From特征实现,我们从不构造它,所以我们选择哪一个并不重要,只要它满足IntoIterator bound.

当然,您仍然希望能够调用print_iter() with Some(...),所以您还需要定义一个转换Option<T> to PrintArg<T>:

impl<T> From<Option<T>> for PrintArg<T> {
    fn from(v: Option<T>) -> Self {
        match v {
            Some(v) => PrintArg::Use(v),
            None => PrintArg::Ignore,
        }
    }
}

有了这些,您的 API 就干净了,允许main()看起来像这样(操场):

fn main() {
    let v = vec![1i32, 2, 3];
    print_iter(Some(v));
    print_iter(Ignore);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有没有办法在使用 Option::None 时提示编译器使用某种默认泛型类型? 的相关文章

随机推荐