简体   繁体   English

Rust - clousures 和泛型类型

[英]Rust - clousures and generic types

To be honest, it's hard for me to describe the problem in words, so i'll show the code right away:老实说,我很难用语言来描述这个问题,所以我会马上展示代码:

// 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() {}

The code above is a simplified model of the situation I find myself in.上面的代码是我发现自己所处情况的简化 model。

If i have |arg: SomeType|如果我有|arg: SomeType| , the c clousure takes reference to generic type T , that implements SomeType - why can't i pass arg as argument for c ? c clousure 引用了泛型类型T ,它实现SomeType - 为什么我不能将arg作为c的参数传递?

Thank you in advance for your help in solving the problem.预先感谢您帮助解决问题。 I apologise for any mistakes in my English.对于我的英语中的任何错误,我深表歉意。

I don't think your current definition of SomeOtherTrait allows this since it leaves filling in the D parameter to the caller by defining it on perform_sth but you internally already bind it to be SomeType by virtue of SomeOtherType::get_some_trait .我不认为您当前对SomeOtherTrait的定义允许这样做,因为它通过在perform_sth上定义它来将D参数填充给调用者,但是您在内部已经通过SomeOtherType::get_some_trait SomeType其绑定为 SomeType 。

If you introduce a generic parameter D on SomeOtherTrait , you can bind D in a given type's implementation of SomeOtherTrait to whatever it requires:如果您在SomeOtherTrait上引入泛型参数D ,则可以将D在给定类型的SomeOtherTrait实现中绑定到所需的任何内容:

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);
        });
    }
}

The other option is adjusting get_some_trait to be generic over the argument to c , although you'll then need to be able to construct it, eg through D::Default() :另一个选项是将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());
    }
}
// ...

which in turn entails adding the D: Default bound to SomeOtherTrait::perform_sth .这反过来又需要添加D: Default绑定到SomeOtherTrait::perform_sth

The issue is that this will only work if D is SomeType .问题是这只有在DSomeType Say for example I have the code bellow:比如说我有下面的代码:

struct Foo;

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

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

This code is completely valid, but the current implementation of perform_sth attempts to use SomeType despite my closure expecting Foo should be used instead.此代码完全有效,但perform_sth的当前实现尝试使用SomeType尽管我的闭包期望Foo应该改用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM