我可以在接受Box<dyn Error + Send>
的地方接受Box<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
。
答案 0 :(得分:0)
这是基于Llaurence_给出的on Reddit答案:
通过将错误类型设置为通用,我可以更改register_callback
以同时接受Box<dyn Error>
和Box<dyn Error + Send>
错误:
fn register_callback<CB, E>(cb: CB)
where
CB: FnOnce() -> StdResult<(), Box<E>>,
E: StdError + ?Sized,
{ /* ... */ }
现在,我可以传递一个返回两种错误/结果的回调:
register_callback(fn_returning_result);
register_callback(fn_returning_sndresult);
答案 1 :(得分:0)
问:我可以在接受Box<dyn Error + Send>
的地方接受Box<dyn Error>
吗?
A:是的,带有一些新型包装。我最终得到的解决方案是:(Playground)
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
特质隐含),并且它们的返回值是有效的{{以及1}},还允许Result
在通话时也使用main
(这要归功于?
特质impl)。