"<T: Trait>"和"where T: Trait"有什么区别?

19
Send特质的文档中,我看到了两个。
impl<T> Send for LinkedList<T> 
where
    T: Send, 

并且

impl<T: Send> Send for LinkedList<T>

这两种语法有什么区别?如果我要为自己的trait编写impl声明,它会对我的代码产生什么影响?
2个回答

19
where子句中定义的特质约束是内联声明的特质约束的超集。内联样式在where子句之前就已经存在;where子句是在RFC 135中引入的:

添加where子句,提供更具表现力的方式来指定特质参数约束。[...]现有的约束符号将作为where子句的语法糖保留。

以下是当前约束语法的一些限制,这些限制可以通过where语法来解决:

  • 它无法表示除类型参数之外的其他约束。因此,如果您有一个泛型函数T,您可以编写T:MyTrait来声明T必须实现MyTrait,但您不能编写Option<T>:MyTrait(int,T):MyTrait。这些形式虽然不太常见,但仍然很重要。

  • 它与关联类型的配合效果不佳。这是因为没有空间来指定关联类型的值。其他语言使用where子句(或类似的东西)来实现这个目的。

  • 它很难阅读。经验表明,当约束数量增加时,当前语法变得难以阅读和格式化。

从那时起,您还可以在where子句中使用更高级别的特征限定for <'a> ...):

fn foo<T, U>()
where
    // higher-ranked trait bounds
    for<'a> T: SomethingElse<'a>,
    // Bound not directly on the generic type
    i32: From<U>,
    T: Iterator,
    // Bound on an associated type
    T::Item: Clone,
    // Just really long
    U: ReallyLong + AnotherReallyLong + WowReallyLong,
{}

如果你的需求可以通过内联特质边界来满足,那么对你的代码没有影响。如果你需要额外的功能,只有where可以提供,那么你需要使用where
另请参阅:

我的个人风格是始终使用"where"形式。对我来说,拥有一个单一的形状,同时在添加新边界时更容易进行"git diff",这比多写一行代码更值得。


2
说实话,这是我渴望 Python 之禅的那种情况之一 :) 另外,历史上存在一些小差异,我记得 ?Sized 一度只能在 where 子句中使用。 - Matthieu M.
3
@MatthieuM. 情况正好相反—— ?Sized 只能内联工作。我还记得,因为我也更喜欢单一的样式(使用 where),但对于 ?Sized 它不起作用... - Shepmaster

1

where从句文档现在包括以下示例:

当单独指定通用类型和边界更清晰时:

impl <A: TraitB + TraitC, D: TraitE + TraitF> MyTrait<A, D> for YourType {}

// Expressing bounds with a `where` clause
impl <A, D> MyTrait<A, D> for YourType where
    A: TraitB + TraitC,
    D: TraitE + TraitF {}

shepmaster提到:

我的个人风格是始终使用where形式。
对我来说,拥有一个单一的形状,而且在添加新的边界时更容易进行git diff,这值得多写一行代码。

我同意,考虑到Git 2.23(2019年第三季度)将在其funcname和words边界中添加rust。

请查看由Johannes Sixt (j6t)于2019年5月30日提交的33be7b3号提交记录
请查看由Marc-André Lureau (``)于2019年5月16日提交的d74e786号提交记录
(在2019年6月21日被Junio C Hamano -- gitster --合并到a41dad4号提交记录中)

userdiff: 为 Rust 添加内置模式

为 Rust 添加了 xfuncnameword_regex 模式,这是一种非常流行的编程语言。
还包括 xfuncname 正则表达式的测试用例(t4018)和更新文档。


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