无法从通用函数中的参考构造(值寿命不够长)

发布于 2025-01-25 16:53:19 字数 1244 浏览 5 评论 0 原文

我有一种方法,可以从中获取一些参数,创建(解密)中间值,并尝试从该中间值构建类型实例。只要固定类型,这种工作正常。如果我想通过仿制药支持多种类型,我会遇到麻烦。这是缩小代码:

impl Factory
{
    pub fn get<'a, T>(&'a self, value: &'a str) -> T
        where T: From<&'a str>
    {
        let value_parsed = value.chars().rev().collect::<String>();
        return T::from(&value_parsed);
    }
}

您可以运行完整的代码在这里。编译会产生以下错误:

31 |     pub fn get<'a, T>(&'a self, value: &'a str) -> T
   |                -- lifetime `'a` defined here
...
35 |         return T::from(&value_parsed);
   |                --------^^^^^^^^^^^^^-
   |                |       |
   |                |       borrowed value does not live long enough
   |                argument requires that `value_parsed` is borrowed for `'a`
36 |     }
   |     - `value_parsed` dropped here while still borrowed

正如我所说,在方法签名中使用 item 而不是通用类型中的情况下,可以摆脱此错误。不要将引用对 t ::来自(),而是移动临时值也是一个选项,但考虑到 value_parsed 实际上并未在此处消费,这几乎没有意义,它与我的代码库的其余部分变得尴尬且不一致。

我可以确保 value_parsed 寿命足够长的时间吗?还是在此处不使用参考文献的其他解决方案?

I have a method that takes some parameters, creates (decrypts) an intermediate value from them and tries to construct a type instance from that intermediate value. This works fine as long as the type is fixed. If I want to support multiple types via generics I run into trouble. Here is minified code:

impl Factory
{
    pub fn get<'a, T>(&'a self, value: &'a str) -> T
        where T: From<&'a str>
    {
        let value_parsed = value.chars().rev().collect::<String>();
        return T::from(&value_parsed);
    }
}

You can run the full code here. Compiling produces the following error:

31 |     pub fn get<'a, T>(&'a self, value: &'a str) -> T
   |                -- lifetime `'a` defined here
...
35 |         return T::from(&value_parsed);
   |                --------^^^^^^^^^^^^^-
   |                |       |
   |                |       borrowed value does not live long enough
   |                argument requires that `value_parsed` is borrowed for `'a`
36 |     }
   |     - `value_parsed` dropped here while still borrowed

As I said, using Item in the method signature rather than a generic type gets rid of this error. Not passing a reference to T::from() but rather moving the temporary value is also an option but that makes little sense given that value_parsed isn’t actually being consumed here, it gets awkward and inconsistent with the rest of my codebase.

Any way I can make sure value_parsed lives long enough? Or is there some other solution short of not using references here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

胡渣熟男 2025-02-01 16:53:19

您将使用较高秩的特征绑定以表明类型任何寿命的值制成

pub fn get<T>(&self, value: &str) -> T
    where T: for<'a> From<&'a str>
          // ^^^^^^^

> t 该 t 可以是从基于 self value 的寿命的参考中构建的局部变量,引用它不能满足终身约束。

You would use a higher-rank trait bound to indicate that the type T can be made from a value with any lifetime, as opposed to a specific lifetime when used as generics on the function:

pub fn get<T>(&self, value: &str) -> T
    where T: for<'a> From<&'a str>
          // ^^^^^^^

What you had before was indicating that T could be built from a reference with the lifetime based on self and value, however, since value_parsed is a local variable, a reference to it cannot satisfy that lifetime constraint.

风和你 2025-02-01 16:53:19

事实证明,在这里使用我自己的特质作品,这不需要我指定签名类型的引用 - 因此,不需要将生命周期与特征相关联:

trait Get<T>
{
    fn get(value: &T) -> Self;
}

使用此特征,方法可以编译:

pub fn get<'a, T>(&'a self, value: &'a str) -> T
    where T: Get<String>
{
    let value_parsed = value.chars().rev().collect::<String>();
    return T::get(&value_parsed);
}

我' m不确定这是否是最好的解决方案,但该解决方案有效。

Turns out using my own trait works here, one that doesn’t require me to specify a reference to the type in the signature – and consequently doesn’t require associating a lifetime with the trait:

trait Get<T>
{
    fn get(value: &T) -> Self;
}

Using this trait the method can compile:

pub fn get<'a, T>(&'a self, value: &'a str) -> T
    where T: Get<String>
{
    let value_parsed = value.chars().rev().collect::<String>();
    return T::get(&value_parsed);
}

I’m not sure whether this is the best solution, but this solution works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文