2016-11-04 45 views
1

構造体のスライスをラップして、構造体を可変または不変にインスタンス化できるようにしようとしています。ここでは、最小限の例です:親構造体と同じ変更可能な構造体フィールドを持つ方法はありますか?

use std::ops::{ Index, IndexMut }; 

struct Test<'a, T: 'a> { 
    inner: &'a[T] 
} 

impl<'a, T: 'a> Test<'a, T> { 
    fn new (inner: &'a[T]) -> Self { Test { inner: inner } } 
} 

impl<'a, T> Index<usize> for Test<'a, T> { 
    type Output = T; 
    fn index (&self, i: usize) -> &T { &self.inner[i] } 
} 

impl<'a, T> IndexMut<usize> for Test<'a, T> { 
    fn index_mut (&mut self, i: usize) -> &mut T { &mut self.inner[i] } 
} 

fn main() { 
    let store = [0; 3]; 
    let test = Test::new (&store); 
    println!("{}", test[1]); 

    let mut mut_store = [0; 3]; 
    let mut mut_test = Test::new (&mut mut_store); 
    mut_test[1] = 42; 
    println!("{}", mut_test[1]); 
} 

これはコンパイルされません:「可変と不変のインデックス付きコンテンツself.inner[..]を借りることができません」。

私はそれがタイプ&'a mut[T]であることがinnerの定義を変更してコンパイルするために取得するが、その後innerことができ、私は(上記の例では、私はその後、可変としてstoreを宣言しなければならないことを、それを必要としない場合でも変更可能ですtestは不変であるにもかかわらず)。

innerの可変性がTestインスタンスの可変性に従うようにする方法はありますか?同様の質問で述べて

答えて

4

、このコードはコンパイルされます。

struct Test<'a, A: 'a> { 
    inner: &'a mut A, 
} 

fn main() { 
    let t = Test { inner: &mut 5i32 }; 

    *t.inner = 9; 
} 

借入内容は不変であっても、借りた要素を変異させることが実際に可能です。これは、拘束力の変更が常に借用されたコンテンツの変更可能性とは無関係であることを念頭に置いて、保証を選択する必要がある場合です。

今、私は2つの可能な解決策を考えることができます:あなたはまだ必要が

impl<'a, A: 'a> Test<'a, A> { 
    fn inner(&self) -> &A { 
     self.inner 
    } 

    fn inner_mut(&mut self) -> &mut A { 
     self.inner 
    } 
} 

:あなたはselfの可変性に依存した方法を超える借りコンテンツを(Playground、コンパイルされません)カプセル化することができます変更可能なコンテンツに借用するために、Testという不変のバインディングから変更することはできません。あなたも、それは不変のコンテンツを指すように必要がある場合は、次の2つの異なる構造体(Playground)を有する考慮する必要があります列挙型で独占的に借りの両方の種類を保つために:

struct Test<'a, A: 'a> { 
    inner: &'a A, 
} 

impl<'a, A: 'a> Test<'a, A> { 
    fn inner(&self) -> &A { 
     self.inner 
    } 
} 

struct TestMut<'a, A: 'a> { 
    inner: &'a mut A, 
} 

impl<'a, A: 'a> TestMut<'a, A> { 
    fn inner(&self) -> &A { 
     self.inner 
    } 

    fn inner_mut(&mut self) -> &mut A { 
     self.inner 
    } 
} 

第三の選択肢があります。ただし、この時点では、借用したコンテンツを変更可能なものとして使用するには、ランタイムチェックが必要です。

関連する問題