【问题标题】:How can I define a trait with arguments and return types like Fn?如何使用参数和返回类型(如 Fn)定义特征?
【发布时间】:2018-03-18 19:45:10
【问题描述】:

我对以下代码感到困惑 (Listing 13-9):

struct Cacher<T>
where
    T: Fn(i32) -> i32,
{
    calculation: T,
    value: Option<i32>,
}

我知道Fn 是一个特征,但通常一个特征没有参数和返回类型。如何定义像Fn 这样的特征?

我试图查看at the definition(实际上是FnOnce,但Fn 绑定了FnMutFnMut 绑定了FnOnce...),但我仍然感到困惑。那个&lt;Args&gt;是什么意思?然后还有something written about it in the Nomicon;但我不明白:

Fn(a, b, c) -&gt; d 本身只是不稳定真实 Fn trait 的糖

【问题讨论】:

    标签: syntax rust closures traits


    【解决方案1】:

    如何定义带有参数和返回类型(如 Fn)的 trait?

    如果您指的是语法MyTrait(A) -&gt; B,则不能。带有“参数”和“返回类型”的特征是特殊的,仅限于 FnFnMutFnOnce 特征。这是硬编码到编译器中的。甚至还有一个特定的错误消息:

    error: parenthetical notation is only stable when used with `Fn`-family traits (see issue #29625)
     --> src/main.rs:5:8
      |
    5 |     A: MyTrait(A) -> B,
      |        ^^^^^^^^^^^^^^^
    

    话虽如此,这种语法脱糖成标准的 trait 语法。您可以从文档中看到 FnOnce 是什么:

    pub trait FnOnce<Args> {
        type Output;
        extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    }
    

    编译器将Fn(A, B, C) -&gt; Z 转换为Fn&lt;(A, B, C), Output = Z&gt;Args 是标准 trait 泛型类型参数,Output 是标准关联类型。 "rust-call" ABI 是一些内部编译器机制,它可以提高效率,并且在大多数情况下可以忽略。

    您完全可以使用泛型参数和关联类型创建自己的特征。只是不允许使用括号符号。

    【讨论】:

    • 嘿,这个错误信息可以修改成更通俗的说法吗?当你应该使用 &lt;&gt; 时,类似于你的东西使用了 () 来表示一个特征? “括号符号”对我来说意味着愚蠢!
    • @JGFMK 鼓励您在Rust repository 上针对此类问题提交问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2018-02-11
    • 2018-07-29
    相关资源
    最近更新 更多