Как я могу создать метод признака, который имеет признак возврата в качестве аргумента? - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть черта B, которая определяет функцию, которая возвращает ссылку на объект, который реализует черту A.

enum Error { }

trait A { }

trait B {
    fn create_a<'a>() -> Result<&'a impl A, Error>;
}

Однако, когда я пытаюсь скомпилировать , я получаю следующую ошибку

error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
  --> src/lib.rs:10:37
   |
10 |     fn create_a<'a>() -> Result<&'a impl A, Error>;
   |                                     ^^^^^^

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

fn create_a<'a>() -> Result<&'a impl A, Error>;

Нет способа создать ссылку, которая будет жить так же долго, как и произвольное время жизни, не имея объекта, у которого уже есть это время жизни и который может выступать в качестве его владельца - и у вас здесь вообще нет объекта, поэтому эта подпись не имеет смысла .

Для дальнейшего рассуждения я предполагаю, что у вас есть аргумент self с этим временем жизни (вероятно, он также должен быть изменяемым): fn create_a<'a>(&'a mut self) -> Result<&'a impl A, Error>;

(обратите внимание, что, поскольку все упомянутые ссылки имеют только один срок службы, вы можете исключить его: fn create_a(&mut self) -> Result<&impl A, Error>;)

Теперь есть два варианта:

  • Вы можете определить конкретный тип как член этой черты, как

    trait B {
        type ImplA: A;
        fn create_a(&mut self) -> Result<&ImplA, Error>;
    }
    

    Это небезопасно для объекта, но оно будет отправлено статически.

    Вы должны иметь возможность использовать псевдоним типа impl при реализации черты, чтобы называть тип при желании.

  • Если вы хотите, чтобы B был безопасным для объекта, используйте ссылку на объект, т.е.

    trait B {
        fn create_a(&mut self) -> Result<&dyn A, Error>;
    }
    

    таким образом, отправка к возвращаемому значению всегда динамична, но вы делаете это, чтобы динамическая отправка в любом случае B::create_a была на первом месте.

0 голосов
/ 06 ноября 2018

Существует несколько способов вернуть черту, все они основаны на некоторой косвенности.

  1. Вы можете вернуть Box<A>
  2. Вы можете вернуть Rc<A> / Arc<A>
  3. Вы можете использовать &dyn A
  4. Вы можете использовать параметр типа T

Разница между 1, 2, 3 и 4 составляет статическое и динамическое распределение .

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