[英]Is there any way to implement Into<&str> or From<T> for &str?
正在用 Rust 編寫一些代碼,試圖定義一個 CLI,使用(否則非常棒) crate clap
,並遇到了一個相當關鍵的問題。 App
方法接受Into<&'help str>
,我一直無法找到實現此特征的方法。
事實上,據我所知,這是絕對無法實現的:
struct JustWorkDamnIt {
string: String
}
impl From<JustWorkDamnIt> for &str {
fn from(arg: JustWorkDamnIt) -> Self {
return arg.string.as_str()
}
}
...產生:
error[E0515]: cannot return value referencing local data `arg.string`
--> src/cmd/interactive.rs:25:16
|
25 | return arg.string.as_str()
| ----------^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `arg.string` is borrowed here
然而,有趣的是,返回一個文字編譯就好了(我認為這就是為什么clap
不介意使用這個特性)。 大概是因為文字被編譯到某個靜態內存區域,因此不屬於該函數:
impl From<JustWorkDamnIt> for &str {
fn from(arg: JustWorkDamnIt) -> Self {
return "literal"
}
}
但是,我的意思是,肯定有一種方法可以實現此特征並返回動態字符串嗎? 也許巧妙地使用 Box<> 之類的,idk。 我相信我已經嘗試了所有我能想到的事情。
如果沒有辦法,那么這對於 Rust 來說似乎是一個非常明顯的缺陷 - 可以在函數頭中聲明和使用的特性,但實際上不能有意義地實現(返回文字沒有多大意義)。 如果結果確實如此,我將在 rust-lang 存儲庫上為此流程創建一個問題,但首先我想在這里檢查我的發現。
UPD:感謝您的評論,讓我更深入地思考這個問題。
問題似乎與生命有關。 我很抱歉沒有展示整個代碼,我認為我分享的片段會充分描述問題,但事后看來,上下文對 Rust 的生命周期很重要確實是有道理的。
我確實為這個特定的問題實例找到了“解決方案”。 由於有問題的代碼在每個可執行文件啟動時只會運行一次,我可以只使用Box::leak
&'static str
並將其稱為一天。 不過,我想弄清楚是否有更通用的解決方案可用於經常創建的動態字符串。
impl Cmd for InteractiveCmd {
fn build_args_parser<'a, 'b>(&'b self, builder: App<'a>) -> App<'a> {
// leak() works here but i'm curious if there's a better way
let staticStr : &'static str = Box::leak(Box::from(format!("Interactive {} shell", APPNAME).as_str()));
let rv = builder
// pub fn about<S: Into<&'b str>>(mut self, about: S) -> Self
.about(staticStr)
.version("0.1");
return rv;
}
}
fn main() {
let interactive = InteractiveCmd::new();
let mut app = App::new(APPNAME)
.version(APPVER)
.author(AUTHORS)
.subcommand(interactive.build_args_parser(App::new("interactive")));
}
目前我在這里面臨兩個困惑點:
impl From<String> for &str
沒有impl From<String> for &str
? 編譯器聲稱impl From<String> for &mut str
存在一個,我在這里沒有看到mut
的重要性。impl From<String> for &str
,那么以某種方式阻止在庫的公共 API 中使用Into<&str>
是否有意義?或者也許問題出在我的 build_args_parser 函數上,就 Rust 而言,它不是將工作卸載給它的選項?
似乎您正在嘗試將String
轉換為&'a str
。 你可以這樣做:
use clap::App;
fn main() {
let s = format!("Interactive {} shell", "Testing");
let app = App::new("Testing")
.about(&*s); // or `.about(s.as_str());` it's the same
}
這是我們要調用的函數的簽名:
pub fn about<S: Into<&'b str>>(self, about: S) -> Self
所以about
參數必須實現 trait Into<&'b str>
。 根據std::convert::Into
,我們知道&'b str
確實實現了特征Into<&'b str>
。 所以現在我們只需要一種方法將String
轉換為&'b str
。 std::string::String
告訴我們有兩種方法:使用s.as_str()
或&*s
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.