泛型 – 为什么我不能在带有类型参数的特征上添加毯子impl?

考虑以下两个特征:

pub trait Foo {
    fn new(arg: u32) -> Self;
}

pub trait Bar<P>: Foo {
    fn with_parameter(arg: u32, parameter: P) -> Self;
}

我想添加毯子impl:

impl<T: Bar<P>, P: Default> Foo for T {
    fn new(arg: u32) -> Self {
        Self::with_parameter(arg, P::default())
    }
}

但是我得到了编译器错误:

error[E0207]: the type parameter `P` is not constrained by the impl trait, self type, or predicates

我想我得到了这个错误,因为我违反了特质一致性规则,但我不明白究竟会破坏什么规则.为什么不允许这种模式?而且,更重要的是,我可以实现我想要的而不会出错吗?

最佳答案
问题是单一类型可以实现Bar< P>.对于P.的多个值,如果你有一个实现Bar< i32>的结构Baz.和Bar< String>,哪个类型应该Foo :: new用于P?

唯一的解决方案是确保单个类型不能多次实现Bar(如果这不是您想要的,那么您的设计就有缺陷!).为此,我们必须用相关类型替换P type参数.

pub trait Bar: Foo {
    type Parameter;

    fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self;
}

impl<T> Foo for T
    where T: Bar, T::Parameter: Default
{
    fn new(arg: u32) -> Self {
        Self::with_parameter(arg, T::Parameter::default())
    }
}

Bar的实现如下所示:

struct Baz;

impl Bar for Baz {
    type Parameter = i32;

    fn with_parameter(arg: u32, parameter: Self::Parameter) -> Self {
        unimplemented!()
    }
}

转载注明原文:泛型 – 为什么我不能在带有类型参数的特征上添加毯子impl? - 代码日志