我可以在接受Box<dyn Error>
的地方接受Box<dyn Error + Send>
吗?如果是,是如何实现的?如果没有,为什么?有没有比下面的例子更优雅的方法?
#![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
。
发布于 2019-05-28 02:44:33
这是基于我通过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);
发布于 2019-05-29 06:36:12
问:我可以在接受Box<dyn Error>
的地方接受Box<dyn Error + Send>
吗?
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
特征的隐含),并且它们的返回值也是有效的Result
,这允许main
在调用时也使用?
(这要归功于StdError
特征的隐含)。
https://stackoverflow.com/questions/56330705
复制相似问题