gpt4 book ai didi

generics - 如果我已经将特征边界添加到另一个 impl block ,为什么还需要在 impl block 上添加特征边界?

转载 作者:行者123 更新时间:2023-11-29 08:12:19 25 4
gpt4 key购买 nike

我有以下代码:

use std::ops::Div;
use std::ops::Mul;

#[derive(Debug)]
struct Foo<T> {
bar: T,
}

impl<T> Foo<T>
where
T: Div<Output = T> + Copy,
{
fn new(bar: T) -> Foo<T> {
let baz = Foo::baz(bar);
Foo { bar: bar / baz }
}
fn baz(bar: T) -> T {
unimplemented!();
}
}

impl<T> Mul for Foo<T>
where
T: Mul<Output = T>,
{
type Output = Foo<T>;

fn mul(self, other: Foo<T>) -> Foo<T> {
Foo::new(self.bar * other.bar)
}
}

但是,编译器会报错:

error[E0277]: cannot divide `T` by `T`
--> src/main.rs:29:9
|
29 | Foo::new(self.bar * other.bar)
| ^^^^^^^^ no implementation for `T / T`
|
= help: the trait `std::ops::Div` is not implemented for `T`
= help: consider adding a `where T: std::ops::Div` bound
note: required by `<Foo<T>>::new`
--> src/main.rs:13:5
|
13 | fn new(bar: T) -> Foo<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
--> src/main.rs:29:9
|
29 | Foo::new(self.bar * other.bar)
| ^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
= help: consider adding a `where T: std::marker::Copy` bound
note: required by `<Foo<T>>::new`
--> src/main.rs:13:5
|
13 | fn new(bar: T) -> Foo<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^

这可以通过修改来解决:

impl<T> Mul for Foo<T>
where
T: Mul<Output = T> + Div<Output = T> + Copy,

为什么我需要添加 Div<Output = T>CopyMul for Foo<T> ?不应该Foo<T>已经满足边界,因为:

impl<T> Foo<T>
where
T: Div<Output = T> + Copy,

最佳答案

每个 impl block 彼此完全不同,包括它们的特征边界——一个 impl block 具有约束这一事实对其他 block 没有任何意义。

在这种情况下,您的 impl block 用于特性 Mul 并不真正需要 Div 特性,因为它可以直接构造 Foo:

impl<T> Mul for Foo<T>
where
T: Mul<Output = T>,
{
type Output = Foo<T>;

fn mul(self, other: Foo<T>) -> Foo<T> {
Foo { bar: self.bar * other.bar }
}
}

只是因为您选择了调用 Foo::new(它具有 DivCopy 要求),所以您的原始版本Mul 将无法编译。这在概念上与这个同样不需要 CopyDiv 的普通函数是同一个问题:

fn x<T>(a: T) -> Foo<T> {
Foo::new(a)
}

请注意,我说的是“impl block ”,而不是“固有的impl block ”或“trait impl block ”。您可以有多个具有不同边界的固有 impl block :

impl<T> Vec<T> {
pub fn new() -> Vec<T> { /* ... */ }
}

impl<T> Vec<T>
where
T: Clone,
{
pub fn resize(&mut self, new_len: usize, value: T) { /* ... */ }
}

这允许类型具有仅在满足特定条件时才适用的功能。

另见:

关于generics - 如果我已经将特征边界添加到另一个 impl block ,为什么还需要在 impl block 上添加特征边界?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49673330/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com