我正在处理一种不能像这样touch 的特征(最小化):

// The associated version
trait Testable {
    type T;
    fn test_it(&self, x: Self::T) -> bool;
}

然后我试着用,比方说,i32:

impl Testable for i32 {
    type T = &str;
    fn test_it(&self, x: Self::T) -> bool {
        x.is_empty()
    }
}

但是,我得到了编译器错误:

type T = &str;
         ^ explicit lifetime name needed here

相关联的类型Self::T正好在方法test_it的输入参数上.为什么编译器声称我必须提供生存期注释?

请注意,如果将T更改为如下所示的泛型类型:

// The generic version
trait Testable<T> {
    fn test_it(&self, x: T) -> bool;
}

impl Testable<&str> for i32 {
    fn test_it(&self, x: &str) -> bool {
        x.is_empty()
    }
}

这一次代码编译时没有错误.

问题是

(1)既然类型只出现在输入参数端,为什么我必须在关联的版本中提供生存期注释?

(2)为什么要编译通用版本?这两个版本之间有什么深层次的区别吗?

推荐答案

不同之处在于,关联类型由特征 Select ,而泛型参数由调用者 Select .因此,使用此代码:

impl Testable for i32 {
    type T = &str;
    fn test_it(&self, x: Self::T) -> bool {
        x.is_empty()
    }
}

编译器需要能够了解关于T的所有信息,而无需查看代码的任何其他部分.但它不能:仅通过查看这段代码就无法知道引用的生存期(顺便说一句,这里唯一可以使用的生存期是'static).

另一方面,使用此代码:

impl Testable<&str> for i32 {
    fn test_it(&self, x: &str) -> bool {
        x.is_empty()
    }
}

&str是一个不完整的类型,因为它错过了生存期,但这没有关系,因为该类型将在调用点填充(与所有模板参数一样).

Rust相关问答推荐

如何从接收&;self的方法克隆RC

MPSC频道在接收器处阻塞

如何正确地将App handler传递给Tauri中的其他模块?

AXUM一路由多个不包括URL的参数类型

我如何使用AWS SDK for Rust获取我承担的角色的凭据?

考虑到Rust不允许多个可变引用,类似PyTorch的自动区分如何在Rust中工作?

Rust 中什么时候可以返回函数生成的字符串切片&str?

Rust 中的静态引用

在 Rust 中,在第一个空格上分割字符串一次

我可以用 Rust 编写一个不可变变量

go 重并堆积MPSC通道消息

枚举的利基优化如何在 Rust 中工作?

如何将 C++ 程序链接到 Rust 程序,然后将该 Rust 程序链接回 C++ 程序? (cpp -> rust -> cpp)

max(ctz(x), ctz(y)) 有更快的算法吗?

仅当函数写为闭包时才会出现生命周期错误

&self 参数在 trait 的功能中是必需的吗?

为什么会出现无法移出可变引用后面的 `self.x`错误?

如何异步记忆选项中的 struct 字段

如果我立即等待,为什么 `tokio::spawn` 需要一个 `'static` 生命周期?

C++ 中的 CRTP 是一种表达其他语言中特征和/或 ADT 的方法吗?