在宏中匹配多个枚举类型
match multiple enum types in macro
我有一个宏,用于将 Box<dyn error::Error>
与不同的枚举相匹配。对于我现在使用的版本,我需要在 if else 链中针对我想要匹配的每种错误类型重复调用它。
#[macro_export]
macro_rules! dyn_match {
($e:expr, $($pat:pat => $result:expr),*) => (
if let Some(e) = $e.downcast_ref() {
match e {
$(
$pat => {$result; true}
),*
}
} else {false}
);
}
...
//fn example(x: u32) -> Result<u32, Box<dyn error::Error>>;
match example(9) {
Ok(_) => Ok(()),
Err(e) => {
if dyn_match!(e,
ExampleError1::ThisError(2) => panic!("it was 2!"),
i => {}
) {Ok(())}
else if dyn_match!(e,
ExampleError2::ThatError(8) => panic!("it was 8!"),
ExampleError2::ThatError(9) => panic!("it was 9!"),
i => {}
) {Ok(())}
else {panic!("{}",e)}
}
}
...
我的目标是做到这一点,这样我就可以将多种错误类型传递给它,它会为每种类型进行单独的匹配。唯一的问题是,要将类型从 Box<dyn error::Error>
转换为其原始错误类型,我需要对其调用 downcast_ref()
。当传递的每个错误都是同一类型时,这工作正常,但是当我尝试为每个提供的手臂调用一个单独的匹配块时,它会抛出错误 cannot infer type for type parameter 'T' declared on the associated function 'downcast_ref'
#[macro_export]
macro_rules! new_dyn_match {
($e:expr, $($pat:pat => $result:expr),*) => (
{
$(
if let Some(e) = $e.downcast_ref() { //cannot infer type for type parameter `T` declared on the associated function `downcast_ref`
if let $pat = e {$result}
}
)*
}
);
}
...
//fn example(x: u32) -> Result<u32, Box<dyn error::Error>>;
match example(9) {
Ok(_) => Ok(()),
Err(e) => {
new_dyn_match!(e,
ExampleError1::ThisError(2) => panic!("it was 2!"),
ExampleError2::ThatError(8) => panic!("it was 8!"),
ExampleError2::ThatError(9) => panic!("it was 9!"),
i => {}
);
Ok(())
}
}
...
我是宏的新手,但看起来,在编译期间展开时,它应该能够看到每个匹配项将与哪种类型进行比较,并隐式向下转换为该类型。我真的不确定如何解决这个问题。有什么想法吗?
知道了!
#[macro_export]
macro_rules! dynmatch {
($e:expr, $(type $ty:ty {$(arm $pat:pat => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
$(
if let Some(e) = $e.downcast_ref::<$ty>() {
match e {
$(
$pat => {$result}
)*
_ => $any
}
} else
)*
{$end}
);
}
...
let _i = match example(3) {
Ok(i) => i,
Err(e) => {
dynmatch!(e, //the dynamic error to be matched
type ExampleError1 { //an error group
arm ExampleError1::ThisError(2) => panic!("it was 2!"), //arm [pattern] => {code}
_ => panic!("{}",e) //_ => {code}
},
type ExampleError2 {
arm ExampleError2::ThatError(8) => panic!("it was 8!"),
arm ExampleError2::ThatError(9) => 9,
_ => panic!("{}",e)
},
_ => panic!("{}",e) //what to do if error group isn't found
)
}
};
...
将解决方案归功于 this crate。
另外,如果有人对更好的解决方案有任何想法,请告诉我!
我有一个宏,用于将 Box<dyn error::Error>
与不同的枚举相匹配。对于我现在使用的版本,我需要在 if else 链中针对我想要匹配的每种错误类型重复调用它。
#[macro_export]
macro_rules! dyn_match {
($e:expr, $($pat:pat => $result:expr),*) => (
if let Some(e) = $e.downcast_ref() {
match e {
$(
$pat => {$result; true}
),*
}
} else {false}
);
}
...
//fn example(x: u32) -> Result<u32, Box<dyn error::Error>>;
match example(9) {
Ok(_) => Ok(()),
Err(e) => {
if dyn_match!(e,
ExampleError1::ThisError(2) => panic!("it was 2!"),
i => {}
) {Ok(())}
else if dyn_match!(e,
ExampleError2::ThatError(8) => panic!("it was 8!"),
ExampleError2::ThatError(9) => panic!("it was 9!"),
i => {}
) {Ok(())}
else {panic!("{}",e)}
}
}
...
我的目标是做到这一点,这样我就可以将多种错误类型传递给它,它会为每种类型进行单独的匹配。唯一的问题是,要将类型从 Box<dyn error::Error>
转换为其原始错误类型,我需要对其调用 downcast_ref()
。当传递的每个错误都是同一类型时,这工作正常,但是当我尝试为每个提供的手臂调用一个单独的匹配块时,它会抛出错误 cannot infer type for type parameter 'T' declared on the associated function 'downcast_ref'
#[macro_export]
macro_rules! new_dyn_match {
($e:expr, $($pat:pat => $result:expr),*) => (
{
$(
if let Some(e) = $e.downcast_ref() { //cannot infer type for type parameter `T` declared on the associated function `downcast_ref`
if let $pat = e {$result}
}
)*
}
);
}
...
//fn example(x: u32) -> Result<u32, Box<dyn error::Error>>;
match example(9) {
Ok(_) => Ok(()),
Err(e) => {
new_dyn_match!(e,
ExampleError1::ThisError(2) => panic!("it was 2!"),
ExampleError2::ThatError(8) => panic!("it was 8!"),
ExampleError2::ThatError(9) => panic!("it was 9!"),
i => {}
);
Ok(())
}
}
...
我是宏的新手,但看起来,在编译期间展开时,它应该能够看到每个匹配项将与哪种类型进行比较,并隐式向下转换为该类型。我真的不确定如何解决这个问题。有什么想法吗?
知道了!
#[macro_export]
macro_rules! dynmatch {
($e:expr, $(type $ty:ty {$(arm $pat:pat => $result:expr),*, _ => $any:expr}),*, _ => $end:expr) => (
$(
if let Some(e) = $e.downcast_ref::<$ty>() {
match e {
$(
$pat => {$result}
)*
_ => $any
}
} else
)*
{$end}
);
}
...
let _i = match example(3) {
Ok(i) => i,
Err(e) => {
dynmatch!(e, //the dynamic error to be matched
type ExampleError1 { //an error group
arm ExampleError1::ThisError(2) => panic!("it was 2!"), //arm [pattern] => {code}
_ => panic!("{}",e) //_ => {code}
},
type ExampleError2 {
arm ExampleError2::ThatError(8) => panic!("it was 8!"),
arm ExampleError2::ThatError(9) => 9,
_ => panic!("{}",e)
},
_ => panic!("{}",e) //what to do if error group isn't found
)
}
};
...
将解决方案归功于 this crate。 另外,如果有人对更好的解决方案有任何想法,请告诉我!