结构中的生命周期和类型说明符问题
Issue with lifetimes and type specifiers in struct
我正在努力解决一个有趣的问题,我发现它与结构定义中的生命周期和类型说明符有关。我想要做的是限制类型为 S
的所有字段 - 定义为 Into<Option<&str>>
,这样我就可以将 Option
或 str
作为值传递对于字段 - 生命周期 'a
定义为结构的生命周期。我正在使用 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..
here
#[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 }
}
}
我接受了 的建议,并决定将边界移动到传递结构的 impl(在本例中为函数)。所以这里的用例是该结构将用于构建具有可选字段的输入数据,然后将其传递给函数。
这解决了我的直接问题,但又是一个小问题,需要在我传入 input
的每个函数上重复边界。所以现在我直接在一个函数下添加所有逻辑,以避免在其他地方重复边界。
#[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);
}
我正在努力解决一个有趣的问题,我发现它与结构定义中的生命周期和类型说明符有关。我想要做的是限制类型为 S
的所有字段 - 定义为 Into<Option<&str>>
,这样我就可以将 Option
或 str
作为值传递对于字段 - 生命周期 'a
定义为结构的生命周期。我正在使用 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..
here
#[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 }
}
}
我接受了
这解决了我的直接问题,但又是一个小问题,需要在我传入 input
的每个函数上重复边界。所以现在我直接在一个函数下添加所有逻辑,以避免在其他地方重复边界。
#[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);
}