2015-06-05 21 views
5

Tôi muốn thực hiện DerefDefrefMut trên một cấu trúc sở hữu một đặc điểm đóng hộp, ví dụ:thực hiện Deref trên một cấu trúc sở hữu một đặc điểm đóng hộp

use std::ops::{Deref, DerefMut}; 

trait Quack { 
    fn quack(&self); 
} 

struct QuackWrap { 
    value: Box<Quack> 
} 

impl Deref for QuackWrap { 
    type Target = Box<Quack>; 

    fn deref<'a>(&'a self) -> &'a Box<Quack> { 
     &self.value 
    } 
} 

impl DerefMut for QuackWrap { 
    fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> { 
     &mut self.value 
    } 
} 

này thất bại trong việc biên dịch với các lỗi sau:

src/main.rs:14:5: 16:6 error: method `deref` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053] 
src/main.rs:14  fn deref<'a>(&'a self) -> &'a Box<Quack> { 
src/main.rs:15   &self.value 
src/main.rs:16  } 
src/main.rs:20:5: 22:6 error: method `deref_mut` has an incompatible type for trait: expected bound lifetime parameter 'a, found concrete lifetime [E0053] 
src/main.rs:20  fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack> { 
src/main.rs:21   &mut self.value 
src/main.rs:22  } 

Nếu tôi thay thế Box<Quack> bằng Box<String> (hoặc một loại tương tự), nó hoạt động. Vấn đề là Quack là một đặc điểm. Nhưng tôi không chắc tại sao lại tạo ra thông báo lỗi. Bất kỳ ý tưởng?

Câu hỏi của tôi tương tự như another SO question, nhưng không hoàn toàn giống nhau. Trong câu hỏi đó, cấu trúc có một tham số kiểu với đặc tính như một ràng buộc. Trong khi đó, trong câu hỏi của tôi, không có tham số kiểu.

Tôi không muốn gây nhầm lẫn các vấn đề, nhưng có một lý do chính đáng là tôi cần Box<Quack> trong đơn đăng ký của mình. I E. Tôi không thể thay thế Quack bằng thông số loại. Trong trường hợp bạn quan tâm, lý do là discussed further in another SO question. hơn

+0

'loại Target = Box ;' là 'loại Target = Hộp ;', và '&' a Box ' là '& 'a Box '. –

Trả lời

6

Khi nghi ngờ, thêm chú thích đời:

use std::ops::{Deref, DerefMut}; 

trait Quack { 
    fn quack(&self); 
} 

struct QuackWrap<'b> { 
    value: Box<Quack + 'b> 
} 

impl<'b> Deref for QuackWrap<'b>{ 
    type Target = Box<Quack + 'b>; 

    fn deref<'a>(&'a self) -> &'a Box<Quack + 'b> { 
     &self.value 
    } 
} 

impl<'b> DerefMut for QuackWrap<'b> { 
    fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'b> { 
     &mut self.value 
    } 
} 
+4

Cụ thể, điều này sẽ giúp vì 'struct QuackWrap {value: Box }' tương đương với 'struct QuackWrap {value: Box }'. – Shepmaster

+0

@Shepmaster Cảm ơn bạn đã giải thích. Tôi không biết chính xác tuổi thọ tiềm ẩn nào đã được thêm vào ở đâu, vì vậy tôi để lại câu trả lời của tôi chỉ là sửa chữa. Trả lời tại sao điều này đã phá vỡ ở nơi đầu tiên là khá hữu ích. –

+0

Cảm ơn bạn cả hai! – rlkw1024

1

Dựa trên câu trả lời của Brian và giải thích Shepmaster, tôi cập nhật mã của tôi như sau. Tôi cũng đã đơn giản hóa cấu trúc QuackWrap. (Đó không phải là thực sự cần thiết, nhưng nó cho là phong cách tốt hơn so với những gì tôi đã làm trước đó.)

use std::ops::{Deref, DerefMut}; 

trait Quack { 
    fn quack(&self); 
} 

struct QuackWrap(Box<Quack>); 

impl Deref for QuackWrap { 
    type Target = Box<Quack + 'static>; 

    fn deref<'a>(&'a self) -> &'a Box<Quack + 'static> { 
     let QuackWrap(ref v) = *self; 
     v 
    } 
} 

impl DerefMut for QuackWrap { 
    fn deref_mut<'a>(&'a mut self) -> &'a mut Box<Quack + 'static> { 
     let QuackWrap(ref mut v) = *self; 
     v 
    } 
} 

Có thể có một cách ngắn gọn hơn để destructure QuackWrap trong derefderef_mut triển khai. Một số quy tắc cú pháp tối nghĩa hơn làm tôi khó chịu. Nhưng bây giờ điều này là tốt.

+0

* Có thể có cách ngắn gọn hơn ... * - Kiểu mới (và tất cả các cấu trúc tuple) cung cấp các trình truy cập vị trí. Đây là [ví dụ nhỏ hơn một chút] (http://is.gd/Q6weUR) – Shepmaster

Các vấn đề liên quan