structopt の validator として指定する関数はfn f(v: String) -> Result<...>
である必要があります。
一方、clapのvalidatorはfn f(v: &str) -> Result<...>
である必要があります。
引数部分の型が違うので AsRef<str> を受け取る関数を作れば、両方のvalidatorとして使えるかと思いした。
しかし、clap側のインターフェースにはライフタイムに関して問題が置きます。
Higher-Order Trait Bound によるライフタイム指定が必要なのかもしれませんが、なかなかうまくいきません。
(そもそも私は Higher-Order Trait Boundに関する詳しくありません。)
以下のコードの structopt, clap 両方の validatorとして使える関数を用意したい場合、以下のコードの validator_for_general をどのように定義すればよいでしょうか?
rust
use clap::Parser;use std::path::PathBuf;use structopt::StructOpt; fn existing_file(pathbuf: PathBuf) -> Result<(), String> { if pathbuf.is_file() { Ok(()) } else { Err(format!("No such file {:?})", pathbuf)) }} pub fn validator_for_general<P>(filepath: P) -> Result<(), String>where P: AsRef<str>,{ let pathbuf = PathBuf::from(filepath.as_ref()); existing_file(pathbuf)} #[derive(Parser)]struct ClapArgs { #[clap(validator = validator_for_general)] file1: PathBuf,} #[derive(StructOpt)]struct StructOptArgs { #[structopt(validator = validator_for_general)] file1: PathBuf,} fn main() {}
error[E0308]: mismatched types | 34 | #[clap(validator = validator_for_general)] | ^^^^^^^^^ lifetime mismatch | = note: expected type `<fn(&str) -> Result<(), std::string::String> {validator_for_general::<&str>} as FnOnce<(&str,)>>` found type `<fn(&str) -> Result<(), std::string::String> {validator_for_general::<&str>} as FnOnce<(&str,)>>` note: the required lifetime does not necessarily outlive the lifetime `'b` as defined here | 29 | #[derive(Parser)] | ^^^^^^ note: the lifetime requirement is introduced here | 1535 | F: FnMut(&str) -> Result<O, E> + Send + 'help, | ^^^^^^^^^^^^ = note: this error originates in the derive macro `Parser` (in Nightly builds, run with -Z macro-backtrace for more info) For more information about this error, try `rustc --explain E0308`. error: could not compile `argumnet_validator_general_interface` due to previous error
各種バージョン
- rustc 1.60.0 (7737e0b5c 2022-04-04)
- clap: 3.1.18 (features = ["derive"])
- structopt: 0.3.26
0 コメント