如何在生锈中实现通用特征的特定类型?

时间:2014-07-16 02:29:41

标签: rust

我最初假设您可以这样做,因为文档(http://doc.rust-lang.org/rust.html#implementations)建议您可以:

trait Bar<T> {
  fn ex(&self) -> T;
}

struct Foo {
  y:f64
}

impl Bar<int> for Foo {
  fn ex(&self) -> int {
    return self.y.floor() as int;
  }
}

impl Bar<uint> for Foo {
  fn ex(&self) -> uint {
    if (self.y < 0.0) {
      return 0u;
    }
    return self.y.floor() as uint;
  }
}

......但这似乎不起作用。我得到的错误如下:

error: multiple applicable methods in scope
error: expected Bar<uint>, but found Bar<int> (expected uint but found int)
error: expected Bar<int>, but found Bar<uint> (expected int but found uint)

所以我想也许Foo必须是通用的,因此每个特定的Foo都有它自己的Bar实现:

trait Bar<T> {
  fn ex(&self) -> T;
}

struct Foo<T> {
  y:f64
}

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    return Foo { y: value } as Foo<U>;
  }
}

impl Bar<int> for Foo<int> {
  fn ex(&self) -> int {
    return self.y.floor() as int;
  }
}

impl Bar<uint> for Foo<uint> {
  fn ex(&self) -> uint {
    if (self.y < 0.0) {
      return 0u;
    }
    return self.y.floor() as uint;
  }
}

fn main() {
  let z = Foo::new::<int>(100.5);
  let q = Foo::new::<uint>(101.5);
  let i:int = z.ex();
  let j:uint = q.ex();
}

...但我的构造函数似乎不起作用:

x.rs:11:12: 11:38 error: non-scalar cast: `Foo<<generic #1>>` as `Foo<U>`
x.rs:11     return Foo { y: value } as Foo<U>;
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error

编辑:我也尝试过:

impl<T> Foo<T> {
  fn new<U>(value:f64) -> Foo<U> {
    let rtn:Foo<U> = Foo { y: value };
    return rtn;
  }
}

解决了转换错误,但结果为:

x.rs:32:11: 32:26 error: cannot determine a type for this expression: unconstrained type
x.rs:32   let z = Foo::new::<int>(100.5);
                  ^~~~~~~~~~~~~~~

O_o我不知道这意味着什么。

你是怎么做到的?

1 个答案:

答案 0 :(得分:9)

impl Bar<int> for Fooimpl Bar<uint> for Foo是一个错误,因为目前每个特征只允许一个impl,类型对(忽略特征上的参数)。 I went into more detail in this answer,包括使用辅助特征的工作,避免必须使Foo通用(可能不是你想要的)。

trait BarForFoo {
    fn do_ex(foo: &Foo) -> Self;
}
impl BarForFoo for int {
    fn do_ex(foo: &Foo) -> int {
        foo.y.floor() as int
    }
}    
impl BarForFoo for uint {
    fn do_ex(foo: &Foo) -> uint {
        foo.y.max(0.0).floor() as uint
    }
}

impl<T: BarForFoo> Bar<T> for Foo {
    fn ex(&self) -> T { BarForFoo::do_ex(self) }
}

第二个错误是因为您在范围&#34;中有两个类型参数TU&#34;对于new函数,但仅指定一个(U)。需要通过撰写T来指定Foo::<int>::...,但我不认为这是您想要的,而是应该在{{1}中使用T泛型功能:

new

作为背景,编译器需要知道impl<T> Foo<T> { fn new(value: f64) -> Foo<T> { ... } } 的具体类型,因为T的实现可能会改变:

new

然后impl<T> Foo<T> { fn new<U>(value:f64) -> Foo<U> { Foo { y: value + std::mem::size_of::<T>() as f64 } } } 会给Foo::<()>::new::<int>(0.0),但y == 0.0会给Foo::<u64>::new::<int>(0.0)