克隆字符串到特定生命周期

Jon*_*eau 3 ownership-semantics rust

我目前正在尝试在Rust中编写一个小命令行应用程序,并且我已经终生难忘.

extern crate clap;
use self::clap::{App, Arg};
use std::env;

impl<'p> Params<'p> {
    fn get_username_arg<'r>() -> Arg<'r, 'r> {
        let mut arg = Arg::with_name("Username")
            .short("u")
            .long("username")
            .takes_value(true);
        match env::var("USERNAME") {
            Ok(username) => {
                // How do I pass `username` to default_value?
                arg.default_value(username)
            }
            Err(e) => arg.required(true),
        }
    }
    // More code below...
}
Run Code Online (Sandbox Code Playgroud)

问题是我正在尝试传递username默认值方法,该方法需要str具有生命周期的方法'r.我尝试克隆,但我无法弄清楚如何告诉它克隆的生命周期是什么.我尝试了以下几点:

let cln = (&*username).clone::<'r>();
arg.default_value(username)
Run Code Online (Sandbox Code Playgroud)

出于某种原因,它现在告诉我,username活得不够长,即使自从克隆数据以来它也无关紧要.

所以我的问题是,如何进行编译?

编辑:我想补充一点,对我来说重要的是签名与生命周期参数保持一致.我不介意做一些昂贵的操作,比如克隆来完成这项工作.

She*_*ter 5

malbarbo提供了一些很好的解决方案,但我想讨论非工作代码的某些方面.

让我们从函数签名开始:

fn get_username_arg<'r>() -> Arg<'r, 'r> {
Run Code Online (Sandbox Code Playgroud)

这表示"对于此函数的调用者选择的任何生命周期,我将返回包含将持续那么长时间的引用".这是一个非常难以维护的承诺,因为呼叫者可以要求满足生命周期的东西,这个价值持续时间更长!事实上,你能够履行"任何一生"义务的唯一方法就是归还一些东西.Arg'staticmain'static

这是一个非常好的迹象,表明会出现问题.另请参见为什么我不能在同一个结构中存储值和对该值的引用?,它将此案例显示为构造函数.许多人跳起来试图String与其一起返回&str,因此答案也可能使该途径短路.^ _ ^

username 虽然自从克隆数据以来无关紧要,但是活不了多久.

username具有非常特定的寿命并且它是有限的.如果你看一段代码,通常可以直截了当地找出一个对象的生命周期:它是变量所在的块的范围而不移动.在你的例子中,username只有在匹配臂的一部分中生活Ok(username) => { // }.一旦该块退出,该值就会被销毁.

clone在这种情况下有一个签名,<'s>clone() -> &'s str如果你Self根据我对Rust的一般理解非常有限而删除了精神(并且具体化).

env::var返回一个Result<String, VarError>,然后你访问Ok变体,制作username一个String.的String实施clone需要一个&String和返回String.我不确定它-> &'s str会从哪里来.

所以,如果我克隆clone::<'r>()它应该强迫一生......

这是一个非常常见的错误.检查Do Rust生命周期是否会影响编译程序的语义?(也许为什么Rust需要明确的生命周期?)来获取一些背景信息.除了重写代码以使引用值具有更大的范围之外,您无法更改其他内容的生命周期.生命周期语法反映了变量的存在时间,它不控制它.没有(安全)方式"强迫"一生.

(&*username).clone 我的意思是那个签名

如果我们取消引用并重新引用a String,我们最终会得到一个&str.这&str将有一个与生命有多久相对应的String寿命.这是有道理的,因为&str它只是指向String.当String取消分配时,&str将指向不再处于有效状态的内存.