繁体   English   中英

结构中的生命周期和类型说明符问题

[英]Issue with lifetimes and type specifiers in struct

我正在努力解决一个有趣的问题,我发现它与结构定义中的生命周期和类型说明符有关。 我想要做的是限制所有类型为S的字段 - 定义为Into<Option<&str>> ,这样我就可以将Optionstr作为字段的值传递给生命周期'a which被定义为结构的生命周期。 我正在使用 rustc 版本1.58.1以防它有帮助。

这是我到目前为止的工作:

#[derive(Debug)]
struct A<S>
where
    S: Into<Option<&'static str>>,
{
    my_field: S,
}

fn main() {
    let obj = A {
        my_field: "hello world",
    };
    println!("{obj:?}");
}

我想删除'static并将其限制为'a 作为参考,我想创建多个类型为S的字段。 我尝试了两种变体,但无法让它与任何一种一起使用。 希望有人能够阐明我做错了什么。

变体 #1

#[derive(Debug)]
struct A<'a, S>
where
    S: Into<Option<&'a str>>,
{
    my_field: S,
}

错误:

error[E0392]: parameter `'a` is never used
  |
2 | struct A<'a, S>
  |          ^^ unused parameter
  |
  = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData

变体 #2

尝试where for..按照这里的建议

#[derive(Debug)]
struct A<S>
where
    for<'a> S: Into<Option<&'a str>>,
{
    my_field: S,
}

错误:

error: implementation of `From` is not general enough
   |
10 |     let obj = A {
   |               ^ implementation of `From` is not general enough
   |
   = note: `Option<&'0 str>` must implement `From<&str>`, for any lifetime `'0`...
   = note: ...but it actually implements `From<&'a str>`

一种方法是遵循编译器的建议并使用PhantomData

#[derive(Debug)]
struct A<'a, S>
where
    S: Into<Option<&'a str>>,
{
    my_field: S,
    _marker: PhantomData<&'a ()>,
}

为了方便起见,您还可以有一个构造函数,这样您就不必重复PhantomData

另一种方法是解除对impl的限制,因为那里的规则不那么严格:

#[derive(Debug)]
struct A<S> {
    my_field: S,
}

impl<'a, S> A<S>
where
    S: Into<Option<&'a str>>
{
    fn new(s: S) -> Self {
        Self { my_field: s }
    }
}

我接受了@Chayim Friedman的建议,并决定将边界移至传递结构的 impl(在本例中为函数)。 所以这里的用例是该结构将用于构建具有可选字段的输入数据,然后将其传递到 function。

这解决了我的直接问题,但又是一个小问题,需要在我传递input的每个 function 上重复边界。 所以现在我直接在 function 下添加所有逻辑,以避免在其他地方重复边界。

#[derive(Debug)]
struct InputStruct<S1, S2> {
    my_field: S1,
    another_field: S2,
}

fn do_something_with_struct<'a, S1: Into<Option<&'a str>>, S2: Into<Option<&'a str>>>(
    input: InputStruct<S1, S2>,
) {
    // do something with input data
    let opt1 = input.my_field.into();
    let opt2 = input.another_field.into();
}

fn main() {
    let obj = InputStruct {
        my_field: "hello world",
        another_field: None,
    };
    println!("{obj:?}");

    do_something_with_struct(obj);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM