Rust - 闭包和泛型

Rust - clousures and generic types

老实说,我很难用语言描述这个问题,所以我马上展示代码:

// SomeType / SomeTrait

struct SomeType;

trait SomeTrait {
    fn do_sth() -> &'static str;
}

impl SomeTrait for SomeType {
    fn do_sth() -> &'static str {
        "do_sth()"
    }
}

// SomeOtherType / SomeOtherTrait

struct SomeOtherType;

impl SomeOtherType {
    fn get_some_trait<C>(&self, c: C)
    where
        C: Fn(SomeType), // Takes clousure, clousure have to get `SomeType`-type paramm 
    {
        c(SomeType);
    }
}

trait SomeOtherTrait {
    fn perform_sth<C, D>(&self, c: C)
    where
        D: SomeTrait,
        C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}

impl SomeOtherTrait for SomeOtherType {
    fn perform_sth<C, D>(&self, c: C)
    where
        D: SomeTrait,
        C: Fn(&D) -> &'static str,
    {
        self.get_some_trait(|arg: SomeType| {
            c(&arg); // <- Problem
            // Error: expected type parameter `D`, found struct `SomeType`
            // But `D: SomeTrait` and SomeType implements `SomeTrait`
        });
    }
}

fn main() {}

上面的代码是我所处情况的简化模型。

如果我有 |arg: SomeType|c clousure 引用通用类型 T,实现 SomeType - 为什么我不能传递 arg 作为 c?

的参数

预先感谢您帮助解决问题。对于我英语中的任何错误,我深表歉意。

我认为您当前对 SomeOtherTrait 的定义不允许这样做,因为它通过在 perform_sth 上定义它来将 D 参数填充给调用者,但您在内部已经绑定它是 SomeType 凭借 SomeOtherType::get_some_trait.

如果在 SomeOtherTrait 上引入通用参数 D,则可以将 SomeOtherTrait 的给定类型实现中的 D 绑定到它需要的任何内容:

trait SomeOtherTrait<D> {
    fn perform_sth<C>(&self, c: C)
    where
        D: SomeTrait,
        C: Fn(&D) -> &'static str; // Takes clousure, clousure have to get type that implements SomeTrait
}

impl SomeOtherTrait<SomeType> for SomeOtherType {
    fn perform_sth<C>(&self, c: C)
    where
        C: Fn(&SomeType) -> &'static str,
    {
        self.get_some_trait(|arg| {
            c(&arg);
        });
    }
}

另一个选项是将 get_some_trait 调整为对 c 的参数通用,尽管您随后需要能够构造它,例如通过 D::Default():

// ...
struct SomeOtherType;

impl SomeOtherType {
    fn get_some_trait<C, D>(&self, c: C)
    where
        D: Default,
        C: Fn(D), // Takes clousure, clousure have to get `SomeType`-type paramm
    {
        c(D::default());
    }
}
// ...

这又需要将 D: Default 绑定到 SomeOtherTrait::perform_sth

问题是这仅在 DSomeType 时有效。比如说我有下面的代码:

struct Foo;

impl SomeTrait for Foo {
    fn do_sth() -> &'static str {
        "Foo"
    }
}

SomeOtherType.perform_sth::<_, Foo>(|_: &Foo| "Bla" );

此代码完全有效,但 perform_sth 的当前实现尝试使用 SomeType,尽管我的闭包预期应使用 Foo