是否可以在泛型函数中排除引用参数?

lje*_*drz 3 generics reference traits rust

由于泛型类型参数T可以是任何类型,包括引用,我想知道是否可以选择退出泛型函数中的引用,即能够编写如下内容:

use std::ops::Deref;

fn foo<T: !Deref>(x: T) -> T {}
Run Code Online (Sandbox Code Playgroud)

但是,这是不允许的,并且在解析阶段就已经中断了。

我读过optin_builtin_traits,但它只支持选择退出自动特征,所以它也不起作用,因为Deref它不是自动特征。

有可能实现这一目标吗?

She*_*ter 6

是的,您可以为此使用自动特征:

#![feature(auto_traits)]
#![feature(negative_impls)]

auto trait NotReference {}

impl<'a, T> !NotReference for &'a T {}
impl<'a, T> !NotReference for &'a mut T {}

fn no_references<T: NotReference>(_: T) {}

fn main() {
    no_references(42); // OK
    no_references(&42); // the trait bound `&{integer}: NotReference` is not satisfied
    no_references("hello"); // the trait bound `&str: NotReference` is not satisfied

    no_references(vec![1, 2, 3]); // OK

    let x = vec![1, 2, 3];
    no_references(x.iter()); // the trait bound `&{integer}: NotReference` is not satisfied in `std::slice::Iter<'_, {integer}>`
}
Run Code Online (Sandbox Code Playgroud)

请注意,这也排除了:

  • 使用'static生命周期引用,如“hello”调用所示
  • 任何包含引用的结构,如iter()调用所示

我可能会排除一些终身问题。

实际上,这就是'staticbound 的作用:

fn foo<T: 'static>(x: T) -> T {}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,自动特征解决方案还将拒绝任何“包含”引用的类型,例如其他人提到的 `S&lt;'a&gt;`。同时,`'static` 绑定将允许 `&amp;'static T`。 (3认同)