2015-03-08 60 views
3

我想要实现FromStr为终身参数结构:如何在具体的生命周期中实现FromStr?

use std::str::FromStr; 

struct Foo<'a> { 
    bar: &'a str, 
} 

impl<'a> FromStr for Foo<'a> { 
    type Err =(); 
    fn from_str(s: &str) -> Result<Foo<'a>,()> { 

     Ok(Foo { bar: s }) 
    } 
} 

pub fn main() { 
    let foo: Foo = "foobar".parse().unwrap(); 
} 

然而,编译器会抱怨:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements 
    --> src/main.rs:11:12 
    | 
11 |   Ok(Foo { bar: s }) 
    |   ^^^ 
    | 
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>,()> 
    --> src/main.rs:9:5 
    | 
9 |  fn from_str(s: &str) -> Result<Foo<'a>,()> { 
    | ^

改变IMPL到

impl<'a> FromStr for Foo<'a> { 
    type Err =(); 
    fn from_str(s: &'a str) -> Result<Foo<'a>,()> { 
     Ok(Foo { bar: s }) 
    } 
} 

给出了这样的错误

error[E0308]: method not compatible with trait 
    --> src/main.rs:9:5 
    | 
9 |  fn from_str(s: &'a str) -> Result<Foo<'a>,()> { 
    | ^lifetime mismatch 
    | 
    = note: expected type `fn(&str) -> std::result::Result<Foo<'a>,()>` 
    = note: found type `fn(&'a str) -> std::result::Result<Foo<'a>,()>` 
note: the anonymous lifetime #1 defined on the block at 9:51... 
    --> src/main.rs:9:52 
    | 
9 |  fn from_str(s: &'a str) -> Result<Foo<'a>,()> { 
    |             ^
note: ...does not necessarily outlive the lifetime 'a as defined on the block at 9:51 
    --> src/main.rs:9:52 
    | 
9 |  fn from_str(s: &'a str) -> Result<Foo<'a>,()> { 
    |             ^
help: consider using an explicit lifetime parameter as shown: fn from_str(s: &'a str) -> Result<Foo<'a>,()> 
    --> src/main.rs:9:5 
    | 
9 |  fn from_str(s: &'a str) -> Result<Foo<'a>,()> { 
    | ^

Playpen

+0

有什么理由不只是做一个构造? – Shepmaster 2015-03-08 20:44:28

+0

是的,我在解析器中使用它,在那里我只持有引用,以便不做任何复制 – 2015-03-08 21:11:01

+1

这是我在http://stackoverflow.com/a/24575591/497043处理的同样的问题;不可能做你想做的事。 – 2015-03-09 01:08:12

回答

6

我不认为你可以在这种情况下执行FromStr

fn from_str(s: &str) -> Result<Self, <Self as FromStr>::Err>; 

在特征定义中没有任何内容将输入的生命周期与输出的生命周期联系在一起。

没有直接回答,但我只是建议作出接受的参考构造:

struct Foo<'a> { 
    bar: &'a str 
} 

impl<'a> Foo<'a> { 
    fn new(s: &str) -> Foo { 
     Foo { bar: s } 
    } 
} 

pub fn main() { 
    let foo = Foo::new("foobar"); 
} 

这有没有任何其它失效模式附带的好处 - 不需要unwrap

你也可以只实施From

struct Foo<'a> { 
    bar: &'a str, 
} 

impl<'a> From<&'a str> for Foo<'a> { 
    fn from(s: &'a str) -> Foo<'a> { 
     Foo { bar: s } 
    } 
} 

pub fn main() { 
    let foo: Foo = "foobar".into(); 
}