2015-11-16 7 views
15

私はこの特性とシンプルな構造を有する:私はBarためFoo形質を実装したいと思います関連タイプで寿命パラメータを指定する方法を教えてください。

use std::path::{Path, PathBuf}; 

trait Foo { 
    type Item: AsRef<Path>; 
    type Iter: Iterator<Item = Self::Item>; 

    fn get(&self) -> Self::Iter; 
} 

struct Bar { 
    v: Vec<PathBuf>, 
} 

を:

impl Foo for Bar { 
    type Item = PathBuf; 
    type Iter = std::slice::Iter<PathBuf>; 

    fn get(&self) -> Self::Iter { 
     self.v.iter() 
    } 
} 

私はこのエラーを取得していますが:

error[E0106]: missing lifetime specifier 
    --> src/main.rs:16:17 
    | 
16 |  type Iter = std::slice::Iter<PathBuf>; 
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected lifetime parameter 

私は、その関連タイプの中で寿命を指定する方法がないことを発見しました。特に、反復子が生涯にわたってselfよりも長生きできないことを表現したいと思います。

この機能を実現するには、Foo形質、またはBar形質導入をどのように変更する必要がありますか?

Rust playground

答えて

13

あなたの問題への解決策は2つあります。最も単純な1から始めましょう:

があなたの特性

trait Foo<'a> { 
    type Item: AsRef<Path>; 
    type Iter: Iterator<Item = Self::Item>; 

    fn get(&'a self) -> Self::Iter; 
} 

に生涯を追加します。これは、あなたが形質を使うどこでも一生に注釈を付ける必要があります。あなたはトレイトを実装するときは、一般的な実装を行う必要があります。

impl<'a> Foo<'a> for Bar { 
    type Item = &'a PathBuf; 
    type Iter = std::slice::Iter<'a, PathBuf>; 

    fn get(&'a self) -> Self::Iter { 
     self.v.iter() 
    } 
} 

あなたは、一般的な引数の形質を必要とする場合、また、あなたの形質オブジェクトへの参照は、同じ寿命を持っていることを確認する必要があります。

fn fooget<'a, T: Foo<'a>>(foo: &'a T) {} 

はあなたのタイプへの参照のためにそれを実装して、代わりにあなたのタイプのための形質を実装するのあなたのタイプ

への参照のための形質を実装します。その形質はこのように生存について何も知る必要はありません。

trait関数は、その引数を値で指定する必要があります。あなたのケースでは、参考のために形質を実装します:

trait Foo { 
    type Item: AsRef<Path>; 
    type Iter: Iterator<Item = Self::Item>; 

    fn get(self) -> Self::Iter; 
} 

impl<'a> Foo for &'a Bar { 
    type Item = &'a PathBuf; 
    type Iter = std::slice::Iter<'a, PathBuf>; 

    fn get(self) -> Self::Iter { 
     self.v.iter() 
    } 
} 

あなたfooget機能は現在、単にこれに伴う問題は、fooget機能がTが現実aであるかを知らないということです

fn fooget<T: Foo>(foo: T) {} 

なり&Barget関数を呼び出すと、実際にはfoo変数から移動しています。オブジェクトから移動しないで、参照を移動するだけです。 fooget関数がgetを2回呼び出すと、この関数はコンパイルされません。

fn fooget_twice<'a, T>(foo: &'a T) 
where 
    &'a T: Foo, 
{} 

where句だけのためにこの関数を呼び出すことを確認します:あなたはfooget機能のみFoo形質が参照用に実装されている引数を受け入れる場合

は、明示的にこのバウンド状態する必要があります型の代わりに参照のためにFooが実装された参照。両方のために実装することもできます。

技術的には、コンパイラが自動的にあなたが

n fooget_twice<T>(foo: &T) 
where 
    &T: Foo, 
{} 

として、それを書くことができfooget_twiceで寿命を推測することができますが、それは十分yetスマートではありません。 Generic Associated Types(GATS):


は、より複雑なケースでは、あなたはまだ実装されていません錆機能を使用することができます。その作業はissue 44265で追跡されています。

+0

「fooget」のような機能の観点から負担が少ないと思われるので、最初のソリューションを使用することにしました。この形質はまた、第2の解決策により明白である。 – mbrt

関連する問題