这段代码无法编译(playground):
struct Mapper<T, U, F>
where
F: Fn(T) -> U,
{
mapper: F,
// _t: PhantomData<T>,
// _u: PhantomData<U>,
}
impl<T, U, F> Mapper<T, U, F>
where
F: Fn(T) -> U,
{
fn new(mapper: F) -> Self {
Self {
mapper,
// _t: PhantomData,
// _u: PhantomData,
}
}
fn call(&self, t: T) -> U {
(self.mapper)(t)
}
}
字符串
编译器说
error[E0392]: parameter `T` is never used
--> src/main.rs:3:15
|
3 | struct Mapper<T, U, F>
| ^ unused parameter
|
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `T` to be a const parameter, use `const T: usize` instead
error[E0392]: parameter `U` is never used
--> src/main.rs:3:18
|
3 | struct Mapper<T, U, F>
| ^ unused parameter
|
= help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `U` to be a const parameter, use `const U: usize` instead
型
然而,这段代码编译,虽然我只为T
添加了PhantomData
:
use std::marker::PhantomData;
struct Mapper<T, U, F>
where
F: Fn(T) -> U,
{
mapper: F,
_t: PhantomData<T>,
// _u: PhantomData<U>,
}
impl<T, U, F> Mapper<T, U, F>
where
F: Fn(T) -> U,
{
fn new(mapper: F) -> Self {
Self {
mapper,
_t: PhantomData,
// _u: PhantomData,
}
}
fn call(&self, t: T) -> U {
(self.mapper)(t)
}
}
型
另一方面,如果我只为U
添加PhantomData
,代码将无法编译:
use std::marker::PhantomData;
struct Mapper<T, U, F>
where
F: Fn(T) -> U,
{
mapper: F,
// _t: PhantomData<T>,
_u: PhantomData<U>,
}
impl<T, U, F> Mapper<T, U, F>
where
F: Fn(T) -> U,
{
fn new(mapper: F) -> Self {
Self {
mapper,
// _t: PhantomData,
_u: PhantomData,
}
}
fn call(&self, t: T) -> U {
(self.mapper)(t)
}
}
fn main() {
let mapper = Mapper::new(|a: usize| -> isize { -(a as isize) });
println!("{}", mapper.call(3));
}
型
为什么?为什么?
1条答案
按热度按时间v7pvogib1#
我认为错误是不正确的。这对于具有泛型和关联类型的常规特征更有意义。
这会编译。
字符串
但这并不重要。
型
这会产生两个错误,即使
Y
是唯一的实际错误。型
如果查看
Fn
的定义,您会发现参数是泛型,而返回值是关联的类型(在FnOnce
上)。因此,关联的类型算作使用,而泛型则不算。请注意,这对大多数代码来说不是问题,因为您使用的是shouldn't put trait bounds on structs except in specific cases。您只需对任何泛型字段使用未绑定泛型,然后将它们绑定到实现中的特征。这样就可以编译了。
型
可能仍然需要
PhantomData
,特别是当您需要实现某个特性时,但是在大多数情况下,您可以重新排列泛型以避免它。