编辑:这个问题显然太复杂了。这是一个更简单的例子,它解释了我想要问的内容:
#[feature(macro_rules)];
macro_rules! trace(
($($arg:tt)*) => (
{ let x = ::std::io::stdout().write_line(format_args!(::std::fmt::format, $($arg)*)); println!("{}", x); }
);
)
#[deriving(Show)]
struct Foo<T> {
data: ~T
}
impl<T> Foo<T> {
// Notice how the 'pontless_marker' variable is passed into this function for
// no reason other than that it allows us to copy the lifetime scope of the
// 'marker' variable in the test below, so the lifetime of the returned pointer
// is valid for that block.
fn returns_to_scope_with_marker<'a>(&'a self, pointless_marker:&'a int) -> &'a ~T {
return &self.data;
}
// This doesn't work, but it should. You should be able to invoke this function
// as something like: let marked = bar.returns_to_scope::<LIFETIME???>();
/*
fn returns_to_scope<'a>(& self) -> &'a ~T {
return &self.data;
}
*/
}
#[test]
fn test_lifetime_return_scope() {
let bar = Foo { data: ~Foo { data: ~10 } };
{
let marker = 10;
let marked = bar.returns_to_scope_with_marker(&marker);
trace!("{:?}", marked);
}
}
参见&#39; pointless_marker&#39;在上面的例子中。
这是我想要避免的。如果该函数也被输入为blah&lt;&#39; a&gt;,我觉得我应该能够使用x.blah ::&lt;这里有东西&gt;()来显式调用它。
那是不是不可能?
答案 0 :(得分:1)
好的,这里有希望解决问题的代码:
#[feature(macro_rules)];
//Macro rules is unchanged
#[deriving(Show)]
struct Foo<'a, T> {
data: &'a T
}
impl<'a, T> Foo<'a, T> {
fn returns_to_scope(&'a self) -> &'a T {
self.data
}
}
fn main() {
let bar = Foo { data: &Foo { data: &10 } };
{
let marked = bar.returns_to_scope();
trace!("{:?}", marked);
}
}
我将逐行(但不按顺序)并解释问题是什么以及如何解决。
首先,你说你想避免警告并避免发送无意义的变量。我同意这些参数是不必要的。为避免向函数添加变量及其参数,生命周期参数将添加到impl
和struct
定义中,如下所示:
struct Foo<'a, T>
...
impl<'a, T> Foo<'a, T>
// note: impl<'a,T> is mandatory, because we can say <'a, int> for example
// which is not what we want
'a
是一个生命周期参数,它充当另一种泛型类型(即T
)。
*如果我们有'a
的生命周期,我们需要将其与某些内容联系起来......我们将在文本稍后修复fn returns_to_scope
后返回此部分,但很明显数据将获得生命周期 - 它是struct Foo中唯一的值,并且它返回的函数需要类似&'a T
的东西。
现在,我们可以在fn returns_to_scope
函数上看起来更好一些。如果你看看原来的功能,你几乎就是正确的。
fn returns_to_scope<'a>(& self) -> &'a ~T {
return &self.data;
}
让我错误的第一件事就是你有一个&~
指针(&'a ~T
)。为什么?您是否理解它是指向堆上分配的指针的堆栈指针?除非你做一些指向杂技的指针,否则它并没有用,但我认为这是一个错误。如果不是很好,你总是可以制作一个~T value
并借用它。
所以你希望你的returns_to_scope
以某种方式返回self.data
字段,如果你要返回一个属于struct Foo的字段,我认为使用相同的生命周期作为结构是更明智的Foo,该领域属于;所以我将描述改为:
fn returns_to_scope(&self) -> &'a T
我省略了<'a>
泛型参数,因为我不需要在'a
生命周期内概括此函数,'a
生命周期是我们通过借用免费获得它的结构的一部分结构。但是我忘了说&self
上的生命周期,所以编译器会抱怨,我只是将&self
更改为使用'a
生命周期进行注释。
fn returns_to_scope(&'a self) -> &'a T
为了画龙点睛,因为Rust只需省略;
即可返回字段,我可以写:
fn returns_to_scope(&'a self) -> &'a T {
self.data
}
而不是return self.data;
。
现在我们看到结构中的字段是'a
生命周期的自然候选者,所以
data: &'a T
被添加到struct Foo中,所有部分现已就绪。