为什么我不能让构造函数在显式定义另一个类型参数时推导出一个类型参数?

时间:2017-06-19 15:28:05

标签: templates generics constructor rust

为什么我不能让构造函数推导出一个类型参数,同时明确地定义另一个类型参数(其中AB应该是不同的)?

struct S<A, B: Default> {
    a: A, b: B
}

impl<A, B: Default> S<A, B> {
    fn new<B>(a: A) -> Self {
        S {
            a: a,
            b: Default::default(),
        }
    }
}

fn main() {
    let s = S::new::<u32>(10);
}

这会出错:

error[E0194]: type parameter `B` shadows another type parameter of the same name
 --> test.rs:6:12
  |
5 | impl<A, B: Default> S<A, B> {
  |         - first `B` declared here
6 |     fn new<B>(a: A) -> Self {
  |            ^ shadows another type parameter                                                                                              

可以重命名内部参数(fn new<B1>),但在尝试使用构造函数时会发生错误:

error[E0282]: type annotations needed
  --> test.rs:15:13
   |
15 |     let s = S::new::<u32>(10);
   |         -   ^^^^^^^^^^^^^ cannot infer type for `B`
   |         |
   |         consider giving `s` a type

如果声明fn new没有任何额外参数,则可以按如下方式创建对象,但这会强制指定两个模板化参数IIUC:

let s = S::<i32, u32>::new(10);

2 个答案:

答案 0 :(得分:3)

我认为你根本不想在函数上指定一个类型参数。相反,您应该只允许编译器在构造结构时使用_作为类型来推断结构的其他类型参数:

struct S<A, B: Default> {
    a: A, b: B
}

impl<A, B: Default> S<A, B> {
    fn new(a: A) -> Self {
        S {
            a: a,
            b: Default::default(),
        }
    }
}

fn main() {
    let s = S::<_, u32>::new(10);
}

答案 1 :(得分:1)

你可以,就是那样。

impl<A> S<A, ()> {
    fn new<C: Default>(a: A) -> S<A, C> {
        S {
            a: a,
            b: Default::default(),
        }
    }
}

在这种情况下,它不会重要 B使用什么类型,因为它永远不会被使用。它只需满足规定的约束条件并充当占位符。

可以使用B作为参数,但我重命名它以明确它与正在实施的类型没有直接关系。