Нет реализации для `T + T` - PullRequest
       0

Нет реализации для `T + T`

0 голосов
/ 07 апреля 2020

В следующем примере:

trait AddStrategy<T> {
    fn do_calc(&mut self, a: T, b: T) -> &Adder<T>;
}
struct Adder<T> {
    val: T,
}

use std::ops::Add;
fn add<T: Add>(a: T, b: T) -> T::Output {
    a + b
}

impl<T> AddStrategy<T> for Adder<T> {
    fn do_calc(&mut self, a: T, b: T) -> &Adder<T> {
        let x = add(a, b); //<---error: no implementation for `T + T`
        self.val = x;
        self
    }
}

Я получаю сообщение об ошибке:

error[E0277]: cannot add `T` to `T`
  --> src/lib.rs:15:17
   |
9  | fn add<T: Add>(a: T, b: T) -> T::Output {
   |    ---    --- required by this bound in `add`
...
13 | impl<T> AddStrategy<T> for Adder<T> {
   |      - help: consider restricting this bound: `T: std::ops::Add`
14 |     fn do_calc(&mut self, a: T, b: T) -> &Adder<T> {
15 |         let x = add(a, b); //<---error: no implementation for `T + T`
   |                 ^^^ no implementation for `T + T`
   |
   = help: the trait `std::ops::Add` is not implemented for `T`

error[E0277]: cannot add `T` to `T`
  --> src/lib.rs:15:17
   |
13 | impl<T> AddStrategy<T> for Adder<T> {
   |      - help: consider restricting this bound: `T: std::ops::Add`
14 |     fn do_calc(&mut self, a: T, b: T) -> &Adder<T> {
15 |         let x = add(a, b); //<---error: no implementation for `T + T`
   |                 ^^^^^^^^^ no implementation for `T + T`
   |
   = help: the trait `std::ops::Add` is not implemented for `T`

Что не так в этом коде?

1 Ответ

3 голосов
/ 07 апреля 2020

Я исправил ваш пример, чтобы вы могли найти ваше рабочее решение на этой детской площадке .

В то время как fn add<T: Add>(a: T, b: T) имеет черту Add для типа T, AddStrategy который вызывает его, не имеет той же границы черты: все что угодно (размером) может использоваться AddStrategy. Поэтому компилятор Rust говорит вам: " Извините, но вы пытаетесь вызвать add для чего-то, что не может быть добавлено ".

Так что Первое, что вам нужно сделать, это связать AddStrategy с Add:

trait AddStrategy<T: Add> { // <--- T: Add
}

И это звучит довольно хорошо, поскольку AddStrategy собирается добавить значения.

То же самое с реализацией черты для Adder:

impl<T: Add> AddStrategy<T> for Adder<T> {  // <--- T: Add

Затем вы должны исправить Adder, потому что он собирается сохранить выходные данные из функции add, которая имеет тип T::Output и Output является типом элемента Add черта:

struct Adder<T: Add> {  // <--- Now Adder is aware about T characteristics
    val: T::Output,     // <--- so you can use `T::Output` from the `Add` trait
}

И так далее: в основном, определяйте черты для типов, и это позволяет вам шаг за шагом исправлять ошибки, пока вы не сделаете все явным.

Альтернатива (которая здесь не кажется полезной, но здесь вы go) состоит в том, что вместо привязки Adder к Add вы можете реализовать AddStrategy тогда и только тогда, когда Adder работает со значениями Add: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d83fd48f88eec68346a3d633e8a7f72c

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...