如何使用具体的生命周期来实现FromStr?

15

我想为一个带有生命周期参数的结构体实现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<'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


有没有理由不把这个变成构造函数? - Shepmaster
是的,我在解析器中使用它,在那里我只保留引用,以便不进行任何复制。 - Piotr Zolnierek
1
这是我在https://dev59.com/ZWAf5IYBdhLWcg3wgy4Y#24575591处理过的同样问题,无法实现你想要的。 - Chris Morgan
1个回答

17

我不相信在这种情况下你可以实现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();
}

为什么FromStr不支持这个?禁止从FromStr :: from_str返回的值引用输入有好的理由吗? - RBF06
@RBF06,“因为它是这样编写的”是最准确的答案。这就是大多数FromStr用法,现在已经稳定了。 - Shepmaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接