が、私は構造体から生涯の汚染を制限することはできますか?
一般的に、あなたは構造体のフィールドのいずれかでそれらを使用している場合は、あなたができません。非常に良い理由が明示されています(Why are explicit lifetimes needed in Rust?参照)。明示的な存続期間を必要とするオブジェクトを含む構造体を取得したら、それを伝播する必要があります。
struct NameRef<'a>(&'a str);
let name = NameRef("Jake"); // 'a is 'static
一つは、また少しの実装に「ノイズ」を軽減できます。具体的な寿命は、コンパイラによって課されているので、通常、これは、構造体の消費者への懸念ではありません
注意next
の定義を用いて定義することができる。Self::Item
の定義を使用する。
impl<'a> Iterator for LogReader<'a > {
type Item = (&'a str,&'a[ConvertedValue]);
fn next(&mut self) -> Option<Self::Item> {
(self.next_fn)(self)
}
}
しかし、あなたの懸念は実際にはもっと深刻な問題を隠し:あなたが言及してきたとは異なり、next
から返される値は、必ずしも構造体からの内部データではありません。彼らは実際に生涯の生涯の間生きています'a
、そしてLogReader
の中の何もその寿命によって実際に拘束されません。
これは二つのことを意味します
(1)私は完全に異なる何かを与える関数を渡すことができ、それがうまく動作します:
static NO_DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some(("wat", NO_DATA))
}
は(2)私は私の機能を望んでいた場合でも、ログリーダーの内部データから何かを返すには、寿命がまったく一致しないために機能しません。のは、何が起こるか見るためにとにかくそれを試してみましょう:
static DATA: &[()] = &[()];
fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
Some((&reader.data[0..4], DATA))
}
fn main() {
let mut a = LogReader {
data: "This is DATA!".to_owned(),
next_fn: my_next_fn
};
println!("{:?}", a.next());
}
コンパイラはあなたにこれを投げるでしょう:匿名の生涯#1は、ログリーダーの寿命がある
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that reference does not outlive borrowed content
--> src/main.rs:26:12
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the body at 25:88...
--> src/main.rs:25:89
|
25 | fn my_next_fn<'a>(reader: &mut LogReader<'a>) -> Option<(&'a str, &'a[ConvertedValue])> {
| _________________________________________________________________________________________^ starting here...
26 | | Some((&reader.data[0..4], DATA))
27 | | }
| |_^ ...ending here
note: ...so that expression is assignable (expected std::option::Option<(&'a str, &'a [()])>, found std::option::Option<(&str, &[()])>)
--> src/main.rs:26:5
|
26 | Some((&reader.data[0..4], DATA))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
を...。 &mut LogReader
の寿命を'a
(&'a mut LogReader<'a>
)にすると、Iterator
を実装しようとするとさらに寿命が延びることになります。これは、基本的に、'a
がLogReader
の値への参照と互換性がないという事実に絞り込んでいます。
これをどのように修正する必要がありますか?
それは戻り値の型が参照を持っているという事実は変わりませんので、寿命の注釈はそれは正確ではありませんが、(生涯エリジオンは、いくつかのケースで発生する可能性があるため)、それに
来ることすべての参照を返すことを避けるか、データを別のオブジェクトに委譲することで、'a
をそのオブジェクトの存続期間にバインドすることができます。あなたの質問に対する答えの最後の部分はIterator returning items by reference, lifetime issueです。
"構造体の内部データへの参照のタプルを返します。"フィールド内の関数オブジェクトではなく、メソッドを必要としませんか?今はメソッドのように 'next_fn'を使っています。 –
フィールドには、オブジェクトのメソッドへのポインタが格納されます。それはいいものではありませんが、私はPythonを移植していますので、うまく翻訳できないものがたくさんあります。 –
Pythonのメソッドは[methods](https://doc.rust-lang.org/book/method-syntax.html)にうまく翻訳できます。 –