2015-02-21 1 views
2

Я хотел бы сделать что-то по следующим направлениям:Привязывание признака переменной продолжительности жизни до & само время жизни

trait GetRef<'a> { 
    fn get_ref(&self) -> &'a [u8]; 
} 

struct Foo<'a> { 
    buf: &'a [u8] 
} 

impl <'a> GetRef<'a> for Foo<'a> { 
    fn get_ref(&self) -> &'a [u8] { 
     &self.buf[1..] 
    } 
} 

struct Bar { 
    buf: Vec<u8> 
} 

// this is the part I'm struggling with: 
impl <'a> GetRef<'a> for Bar { 
    fn get_ref(&'a self) -> &'a [u8] { 
     &self.buf[1..] 
} 

Точка явного пожизненной переменной в GetRef признака, чтобы возвращаемое значение get_ref() на a Foo объект, чтобы пережить сам Foo, привязывая время жизни возвращаемого значения к времени жизни буфера Foo.

Однако я не нашел способ реализовать GetRef для Bar таким образом, который принимает компилятор. Я попробовал несколько вариантов вышеизложенного, но не могу найти то, что работает. Есть ли какая-либо причина, по которой это принципиально невозможно сделать? Если нет, как я могу это сделать?

ответ

4

Связывание переменной пожизненную признака для & самостоятельной жизни

не представляется возможным.

Есть ли какая-либо причина, по которой это принципиально невозможно сделать?

Да. Собственный вектор - это нечто иное, чем заимствованный фрагмент. Ваша черта GetRef имеет смысл только для вещей, которые уже представляют собой «кредит» и не владеют срезом. Для типа владения, такого как Bar, вы не можете безопасно вернуть заемный кусочек, который выделяется Self. Это то, что средство проверки займов препятствует обманутым указателям.

Что вы пытались сделать, это связать параметр времени жизни с временем жизни Self. Но срок службы Self не является собственностью его типа. Это зависит только от того, в какой области было определено это значение. И поэтому ваш подход не может работать.

Еще один способ взглянуть на это: в черте вы должны быть четко оговорены ли Self способом и его результатом или нет. Вы определили черту GetRef, чтобы вернуть что-то не, связанное с Self w.r.t. время жизни. Итак, нет заимствований. Таким образом, он не реализуется для типов, которые владеют данными. Вы не можете создать заимствованный фрагмент, ссылаясь на элементы Vec, не заимствуя Vec.

Если нет, как я могу это сделать?

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

trait GetRef { 
    fn get_ref(&self) -> &[u8]; 
} 

Значением этого признака является то, что get_refзаимствуетSelf и возвращает вид «займа» из-за текущих правил элиминации жизни.Это эквивалентно более явной форме

trait GetRef { 
    fn get_ref<'s>(&self) -> &'s [u8]; 
} 

Это может быть реализовано для обоих типов в настоящее время:

impl<'a> GetRef for Foo<'a> { 
    fn get_ref(&self) -> &[u8] { &self.buf[1..] } 
} 

impl GetRef for Bar { 
    fn get_ref(&self) -> &[u8] { &self.buf[1..] } 
} 
+0

Ваш код в конце ответа в значительной степени зависит от того, что у меня есть сейчас и от чего я пытаюсь убежать. Причина, по которой я хочу сделать это, немного запутанна, но сводится к тому, что мне нужно получить кусочки, которые переживают «Foo», из которого они происходят (но не базовый буфер). – fjh

+1

@fjh Я думаю, что ключевым моментом здесь является то, что в черте жизненное время всегда должно иметь одинаковую «форму» - это может быть либо время жизни, на которое параметризуется конструктор, либо может быть самим объектом, но он не могут быть обоим. В вашем примере, когда 'Bar' умирает *, так и буфер * - буфер не может быть дольше. – Shepmaster

+0

@Shepmaster Да, я понимаю, что ссылка на 'Bar' не может пережить сам« Бар », но я надеялся, что есть способ заставить это работать с« Foo », не создавая для« Бар »невозможность , Я достаточно убежден, что это невозможно сделать сейчас. Баммер, однако. – fjh

0

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

trait GetRef<'a, 'b> { 
    fn get_ref(&'b self) -> &'a [u8]; 
} 

struct Foo<'a> { 
    buf: &'a [u8] 
} 

impl <'a, 'b> GetRef<'a, 'b> for Foo<'a> { 
    fn get_ref(&'b self) -> &'a [u8] { 
     &self.buf[1..] 
    } 
} 

struct Bar { 
    buf: Vec<u8> 
} 

// Bar, however, cannot contain anything that outlives itself 
impl<'a> GetRef<'a, 'a> for Bar { 
    fn get_ref(&'a self) -> &'a [u8] { 
     &self.buf[1..] 
    } 
} 


fn main() { 
    let a = vec!(1 as u8, 2, 3); 
    let b = a.clone(); 
    let tmp; 
    { 
     let x = Foo{buf: &a}; 
     tmp = x.get_ref(); 
    } 
    { 
     let y = Bar{buf: b}; 
     // Bar's buf cannot outlive Bar 
     // tmp = y.get_ref(); 
    } 
}