rust - 如何接受`Box` 在接受 `Box 的地方`?
问题描述
我可以在接受的Box<dyn Error + Send>
地方接受 aBox<dyn Error>
吗?如果是,如何?如果不是,为什么,还有比下面的例子更优雅的方法吗?
#![allow(unused)]
use std::error::Error as StdError;
use std::result::Result as StdResult;
type Result = StdResult<(), Box< dyn StdError >>;
type SndResult = StdResult<(), Box< dyn StdError + Send >>;
fn fn_returning_result() -> Result { Ok(()) }
fn fn_returning_sndresult() -> SndResult { Ok(()) }
/// Accept a callback that returns a non-Send `Result`.
fn register_callback<CB: FnOnce() -> Result>(cb: CB) { /* ... */ }
fn main() -> Result {
// Is there a way to get rid of ... vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv ... this part?
let cb = || fn_returning_sndresult().map_err(|e| -> Box<dyn StdError> { e });
register_callback(cb);
Ok(())
}
编辑:我想在这里做的只是let cb = || fn_returning_sndresult();
,但这不会编译。
另外,我想使用单个返回类型调用回调fn_returning_result()?
或在回调内部调用,而无需执行.fn_returning_sndresult()?
map_err
解决方案
问:我可以在接受的Box<dyn Error + Send>
地方接受Box<dyn Error>
吗?
A:是的,有一些新的包装。我最终得到的解决方案是:(游乐场)
use std::error::Error as StdError;
use std::result::Result as StdResult;
use std::fmt;
type Result = StdResult<(), Box< dyn StdError >>;
type SndResult = StdResult<(), Box< dyn StdError + Send >>;
fn fn_returning_result() -> Result { dbg!(Err("oops".into())) }
fn fn_returning_sndresult() -> SndResult { dbg!(Ok(())) }
/// Result type using `Er` defined below.
type Rt<T = ()> = StdResult<T, Er>;
// Error wrapper
#[derive(Debug)]
struct Er(Box<dyn StdError>);
impl fmt::Display for Er {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl StdError for Er {}
// Allow `?` operator
impl From<Box<dyn StdError>> for Er {
fn from(err: Box<dyn StdError>) -> Self {
Er(err)
}
}
impl From<Box<dyn StdError + Send>> for Er {
fn from(err: Box<dyn StdError + Send>) -> Self {
Er(err)
}
}
// List of callbacks
struct Callbacks<'a>(Vec<Box<dyn FnOnce() -> Rt + 'a>>);
impl<'a> Callbacks<'a> {
fn new() -> Self {
Callbacks(Vec::new())
}
fn add(&mut self, cb: impl FnOnce() -> Rt + 'a) {
self.0.push(Box::new(cb));
}
fn pop_and_call(&mut self) -> Rt {
self.0.pop().unwrap()()
}
}
// Example
fn main() -> Result {
let mut callbacks = Callbacks::new();
callbacks.add(|| { Ok(fn_returning_result()?) });
callbacks.add(|| { Ok(fn_returning_sndresult()?) });
callbacks.pop_and_call()?;
callbacks.pop_and_call()?;
Ok(())
}
请注意,回调可以?
在其中一个Result
或SndResult
值上使用(感谢From
trait impls),并且它们的返回值也是有效Result
的,允许main
也用于?
他们的调用(感谢StdError
trait impls)。
推荐阅读
- c - 链接 2 个源文件而不是使用头文件有什么意义?
- powershell - Word ExportAsFixedFormat
- arrays - 在 Golang 中添加 2 个数组类型
- string - 如何在 Golfscript 中为字符串添加单个反斜杠?
- node.js - 无法将 nodejs 部署到 azure
- reactjs - 将 `console.log` 添加到所有 `useEffect`
- go - Go 例程后关闭冗余 sql.Rows 对象的推荐方法
- python - 是否可以使用 requests 模块从 Reverso Context 获取带有单词翻译的例句?
- javascript - JS - 强制打印死键
- powershell - 按数字动态分组对象Powershell