如何将 clap::ArgMatches 存储在结构中?

问题描述

我正在尝试将 clap::ArgMatches 存储在这样的结构中:

struct Configurator {
    cli_args: ArgMatches,root_directory: String
}

我收到的错误是:

error[E0106]: missing lifetime specifier
 --> src/configurator.rs:5:15
  |
5 |     cli_args: ArgMatches,|               ^^^^^^^^^^ expected named lifetime parameter
  |
help: consider introducing a named lifetime parameter
  |
4 | struct Configurator<'a> {
5 |     cli_args: ArgMatches<'a>,|

我尝试了错误输出中给出的建议解决方案,但这似乎导致了不同的错误

这里有更多的上下文:

extern crate clap;
use clap::{Arg,App,ArgMatches};

struct Configurator {
    cli_args: ArgMatches,root_directory: String
}

impl Configurator {
    pub fn build() -> Configurator {
        let configurator = Configurator {};

        // returns ArgMatches apparently 
        let cli_args = App::new("Rust Web Server")
            .version("0.0.1")
            .author("Blaine Lafreniere <brlafreniere@gmail.com>")
            .about("A simple web server built in rust.")
            .arg(Arg::with_name("root_dir")
                .short("r")
                .long("root_dir")
                .value_name("ROOT_DIR")
                .help("Set the root directory that the web server will serve from.")
                .takes_value(true))
            .get_matches();
        
        configurator.cli_args = cli_args;
    }
}

解决方法

如错误消息所示,您必须向 Configurator 添加命名生命周期说明符。这是因为 ArgMatches 持有对值的引用,因此您必须告诉 Rust 这些引用将存活多长时间:

struct Configurator<'a> {
    cli_args: ArgMatches<'a>,root_directory: String
}

您必须对 impl 块执行相同的操作:

impl<'a> Configurator<'a> {
    pub fn build() -> Configurator<'a> {
      // ...
    }
}

您的代码的另一个问题是,在 Rust 中,您必须在实例化结构时初始化所有字段:

// this doesn't work
let config = Configurator {}

// but this does
let config = Configurator {
  cli_args: cli_args,root_directory: "/home".to_string(),};

最后,您必须从函数中返回 Configurator

pub fn build() -> Configurator<'a> {
    let cli_args = App::new("Rust Web Server")
        .version("0.0.1")
        .author("Blaine Lafreniere <brlafreniere@gmail.com>")
        .about("A simple web server built in rust.")
        .arg(
            Arg::with_name("root_dir")
                .short("r")
                .long("root_dir")
                .value_name("ROOT_DIR")
                .help("Set the root directory that the web server will serve from.")
                .takes_value(true),)
        .get_matches();

    return Configurator {
        cli_args: cli_args,};
}

这是一个 runnable example

,

由于您仅使用 App 字符串构建 'static,因此 .arg_matches() 的返回类型是 ArgMatches<'static>,您应该在 Configurator 结构定义中明确说明.这比使用像 'a 这样的通用生命周期参数要好得多,因为它不会用任何生命周期注释“感染”您的 Configurator 结构。此外,您不能在 Rust 中“部分”初始化结构,它们必须完全初始化,因此当所有数据准备就绪时,我已将 Configurator 结构的构造移到 build 函数的底部。

use clap::{Arg,App,ArgMatches};

struct Configurator {
    cli_args: ArgMatches<'static>,root_directory: String
}

impl Configurator {
    pub fn build(root_directory: String) -> Configurator {
        let cli_args = App::new("Rust Web Server")
            .version("0.0.1")
            .author("Blaine Lafreniere <brlafreniere@gmail.com>")
            .about("A simple web server built in rust.")
            .arg(Arg::with_name("root_dir")
                .short("r")
                .long("root_dir")
                .value_name("ROOT_DIR")
                .help("Set the root directory that the web server will serve from.")
                .takes_value(true))
            .get_matches();
        
        Configurator {
            cli_args,root_directory,}
    }
}

playground