我想要一个返回多种类型的Range
的函数(例如Range
,RangeFrom
,RangeTo
)。我的目标是检查值是在编译时我们不知道的范围内(无论它们是打开还是关闭)。
我试图通过指定RangeBounds
的返回类型来做到这一点。不幸的是,因为.contains
是通用的,所以我认为这是不可能的。
还有另一种方法吗?还是我应该只传递(Option<isize>, Option<isize>)
,并手动检查它们的值?
这个问题比解释这个具体错误更广泛-我正在尝试寻找是否还有另一种方法可以实现目标。我想使用标准库Range
工具,而不是自定义实现。
use std::ops::{Range, RangeBounds};
fn range(start: Option<isize>, end: Option<isize>) -> dyn RangeBounds<isize> {
match (start, end) {
(Some(s), Some(e)) => Range { s, e },
// other options here
_ => panic!(),
}
}
原因:
error[E0038]: the trait `std::ops::RangeBounds` cannot be made into an object
--> src/lib.rs:3:1
|
3 | fn range(start: Option<isize>, end: Option<isize>) -> dyn RangeBounds<isize> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::ops::RangeBounds` cannot be made into an object
|
= note: method `contains` has generic type parameters
另一种无效的方法:
use std::ops::{Range, RangeBounds, RangeFrom, RangeTo};
fn range(start: Option<isize>, end: Option<isize>) -> impl RangeBounds<isize> {
match (start, end) {
(Some(s), Some(e)) => Range { start: s, end: e },
(Some(s), None) => RangeFrom { start: s },
// other options here
_ => panic!(),
}
}
error[E0308]: match arms have incompatible types
--> src/main.rs:18:28
|
16 | / match (start, end) {
17 | | (Some(s), Some(e)) => Range { start: s, end: e },
| | --------------------------- this is found to be of type `std::ops::Range<isize>`
18 | | (Some(s), None) => RangeFrom { start: s },
| | ^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::ops::Range`, found struct `std::ops::RangeFrom`
19 | | // other options here
20 | | _ => panic!(),
21 | | }
| |_____- `match` arms have incompatible types
最佳答案
你不知道您不能返回不安全对象特征的特征对象。已经对此进行了详尽的解释:
而是定义您自己的对象安全特征,并根据非对象安全特征来实现它:
use std::ops::{Range, RangeBounds};
trait MyBounds {
fn contains(&self, v: &isize) -> bool;
}
impl<T> MyBounds for T
where
T: RangeBounds<isize>,
{
fn contains(&self, v: &isize) -> bool {
RangeBounds::contains(self, v)
}
}
fn range(start: Option<isize>, end: Option<isize>) -> Box<dyn MyBounds> {
match (start, end) {
(Some(start), Some(end)) => Box::new(Range { start, end }),
// other options here
_ => panic!(),
}
}
也可以看看:
关于rust - 如何返回实现非对象安全特征的多种类型之一?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57277497/