как объявить время жизни enum с помощью функции impl? - PullRequest
1 голос
/ 11 октября 2019

Я хотел бы объявить enum с функцией доступа, которая возвращает значения, которые были предоставлены при создании значения. Ниже приведен надуманный пример, иллюстрирующий ошибку:

use std::mem;

#[derive(Debug)]
enum SomeBytes<'a> {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes<'a> {

  pub fn get_bytes(&'a self) -> &'a[u8] {
    use SomeBytes::*;

    match *self {
      One(byte_array) => &byte_array,
      Two(byte_array) => &byte_array,
    }
  }
}

fn main() {
  let var1 = SomeBytes::One(*b"A");
  let var2 = SomeBytes::Two(*b"AB");

  println!("one byte = {:?}", var1);
  println!("sizeof one byte = {:?}", mem::size_of_val(&var1));
  println!("two bytes = {:?}", var2);
  println!("sizeof two bytes = {:?}", mem::size_of_val(&var2));
}

error:

  Compiling playground v0.0.1 (/playground)
error[E0261]: use of undeclared lifetime name `'a`
 --> src/main.rs:9:16
  |
9 | impl SomeBytes<'a> {
  |                ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:11:21
   |
11 |   pub fn get_bytes(&'a self) -> &'a[u8] {
   |                     ^^ undeclared lifetime

error[E0261]: use of undeclared lifetime name `'a`
  --> src/main.rs:11:34
   |
11 |   pub fn get_bytes(&'a self) -> &'a[u8] {
   |                                  ^^ undeclared lifetime

Как мне написать этот код, чтобы он компилировался?

См. Rust Playground

Если я удалю все времена жизни из своего кода (какие текущие комментарии / ответы говорят, что они не нужны, то пример выглядит следующим образом:

use std::mem;

#[derive(Debug)]
enum SomeBytes {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes {

  pub fn get_bytes(&self) -> &[u8] {
    use SomeBytes::*;

    match *self {
      One(byte_array) => &byte_array,
      Two(byte_array) => &byte_array,
    }
  }
}

fn main() {
  let var1 = SomeBytes::One(*b"A");
  let var2 = SomeBytes::Two(*b"AB");

  println!("one byte = {:?}", var1);
  println!("sizeof one byte = {:?}", mem::size_of_val(&var1));
  println!("two bytes = {:?}", var2);
  println!("sizeof two bytes = {:?}", mem::size_of_val(&var2));
}

, которыйвыдает мне следующую ошибку:

Compiling playground v0.0.1 (/playground)
error[E0515]: cannot return value referencing local variable `byte_array`
  --> src/main.rs:14:5
   |
14 | /     match *self {
15 | |       One(byte_array) => &byte_array,
16 | |       Two(byte_array) => &byte_array,
   | |                          ----------- `byte_array` is borrowed here
17 | |     }
   | |_____^ returns a value referencing data owned by the current function

error[E0515]: cannot return value referencing local variable `byte_array`
  --> src/main.rs:14:5
   |
14 | /     match *self {
15 | |       One(byte_array) => &byte_array,
   | |                          ----------- `byte_array` is borrowed here
16 | |       Two(byte_array) => &byte_array,
17 | |     }
   | |_____^ returns a value referencing data owned by the current function

Я должен был добавить время жизни в попытке исправить вышеуказанную ошибку, но это не было решением. Я пытался сказать компилятору, что я не хочувернуть что-то, принадлежащее текущей функции ... Может кто-нибудь объяснить соответствующее исправление?

1 Ответ

3 голосов
/ 11 октября 2019

Stargateur дал вам код без объяснения причин;давайте посмотрим, смогу ли я заполнить пробелы.

Причина, по которой ваш код не работает, заключается в том, что объявление времени жизни на struct связывает это время жизни со структурой . Другими словами, каждый метод, использующий или возвращающий 'a в вашем случае, будет принимать или возвращать один и тот же 'a независимо от того, где и как это было размещено. Это имеет смысл, когда у вас есть ссылка внутри struct, которой у вас нет. В результате в этом нет необходимости.

Если бы вы хотели указать всю свинью и указать время жизни, вы могли бы сделать это следующим образом:

#[derive(Debug)]
enum SomeBytes {
  One([u8; 1]),
  Two([u8; 2]),
}

impl SomeBytes {

  pub fn get_bytes<'a>(&'a self) -> &'a [u8] {
    use SomeBytes::*;

    match self {
      One(ref byte_array) => byte_array,
      Two(ref byte_array) => byte_array,
    }
  }
}

Время жизни определяется каксвойство метода , а не struct. Его дополнительное требование очевидно - необходимо &self на весь срок жизни 'a гарантировать, что его возвращаемый параметр также будет подчиняться.

Однако это педантизм;на практике это требование срока службы не является обязательным и может быть отброшено в пользу более простой, более автоматической версии:

  pub fn get_bytes(&self) -> &[u8] {
    use SomeBytes::*;

    match self {
      One(ref byte_array) => byte_array,
      Two(ref byte_array) => byte_array,
    }
  }

Примечание. Чтобы этот пример работал, & также необходимо удалить перед byte_array на правой стороне матча. Поскольку ваш метод принимает &self, содержимое ваших сопоставлений с образцом будет самим ссылками, даже если вы сопоставляете себя (так как у вас нет владения объектом), и в результате & приведет к ссылке на-a ссылка

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