由于泛型类型参数 T
可以是任何类型,包括引用类型,我想知道是否有可能在泛型函数中排除引用类型,也就是能否像下面这样编写:
use std::ops::Deref;
fn foo<T: !Deref>(x: T) -> T {}
然而,这是不被允许的,并且在解析阶段就已经出现了错误。
我读到了关于
optin_builtin_traits
的内容,但它仅支持选择退出自动特性,因此也无法使用,因为Deref
不是自动特性。是否有可能实现这个?
由于泛型类型参数 T
可以是任何类型,包括引用类型,我想知道是否有可能在泛型函数中排除引用类型,也就是能否像下面这样编写:
use std::ops::Deref;
fn foo<T: !Deref>(x: T) -> T {}
optin_builtin_traits
的内容,但它仅支持选择退出自动特性,因此也无法使用,因为Deref
不是自动特性。是的,您可以使用自动特性来实现这一点:
#![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}>`
}
iter()
调用所示实际上,这就是我可能可以排除一些生命周期问题。
'static
限制的作用:fn foo<T: 'static>(x: T) -> T {}
auto
是保留给现有的 std
特性,所以我试图用 Deref
想出一些解决方法。这个解决方法可能会很有用。 - ljedrzstruct S<'a> { val: &'a str }
。 - mcartonS<'a>
。与此同时,'static
约束将允许 &'static T
。 自动派生 trait 解决方案还会拒绝包含引用(如其他人提到的 S<'a>
)的任何类型。而 'static
约束可以接受 &'static T
。 - kennytm
!Deref
,也无法帮助你解决这些问题。对我来说,这种情况感觉像是一个XY问题。 - Wesley WiserT
是一个引用的内容,但我认为如果T
包含一个引用的话,情况也是一样的。比如:struct S<'a> { val: &'a str }
。编译器必须确保任何类型为T
的值在你返回的东西的生命周期内仍然有效。不过我可能有所错误... - Wesley Wiser