如何在关联类型中有一个无法命名的情况下实现trait?

10

我有一个返回 impl Trait 的函数,因此我无法访问具体的返回类型。 我需要将该函数的返回值用作 trait 中的关联类型。如何实现?

这是一个简化的例子:

fn f() -> impl Iterator<Item = u8> {
    std::iter::empty()
}

struct S;

impl IntoIterator for S {
    type Item = u8;
    type IntoIter = (); // What can I write here ?

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}

不使用将迭代器转换为Box类型的情况下,这是否可能实现?


2
恭喜您提出了一个措辞得当、带有适当 MCVE 的问题! - Shepmaster
1个回答

8
很遗憾,你现在还不能这样做。至少目前还不行。有一项RFC(称为存在类型和impl Trait变量声明)跟踪问题),它允许你在模块级别上声明一个公共类型名称,其类型定义是从其在模块中的使用方式推断出来的。模块的用户可以通过其公共名称引用此类型,并且可以将其用作关联类型。很难猜测新功能何时会稳定下来,在此期间确实没有太多好的选择。除了可能仅因为您的用例具体情况而起作用的事物之外,一般的解决方法是使用trait对象:
impl IntoIterator for S {
    type Item = u8;
    type IntoIter = Box<dyn Iterator<Item = u8>>;

    fn into_iter(self) -> Self::IntoIter {
        Box::new(f())
    }
}

如果可以使用夜间特性,您可以在RFC稳定之前帮助测试它:
#![feature(existential_type)]

impl IntoIterator for S {
    type Item = u8;
    existential type IntoIter: Iterator<Item = u8>;

    fn into_iter(self) -> Self::IntoIter {
        f()
    }
}

2
谢谢您的清晰回答。那我就使用Box吧。感觉被Rust背叛了,它曾经承诺过给我零成本抽象 :p - lovasoa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接