在函数中使用不可单态化的泛型参数
Using non-monomorphizable generic parameters in a function
我想编写一些代码,这些代码在特定特征的实现者之间应该是通用的,但直到运行时才能知道其确切类型。
特别是,我想将 PartialOrd
中的函数应用于给定枚举中的部分案例。这是我要实现的基本版本:
enum Value {
String(String),
Float(f64),
Array(Vec<Value>),
}
fn apply_op<T, F>(v: &Value, compare_val: &Value, op: F) -> bool
where
F: FnOnce(&T, &T) -> bool,
T: PartialOrd,
{
match (v, compare_val) {
(Value::String(s), Value::String(compare_str)) => op(s, compare_str),
(Value::Float(f), Value::Float(compare_f)) => op(f, compare_f),
_ => false,
}
}
然后为 op
传入类似 PartialOrd::gt
的内容。
由于类型 T
由 match arm 确定,因此无法单态化,因此无法编译。
有没有办法解决这个问题,也许可以使用某种 trait/wrapper 结构骗局?
Playground link here,其中包括上面的版本(无法编译)和我目前用来解决这个问题的宏方法。宏没问题,不过真的感觉不用宏也可以。
您不能 late-bind 通用函数,但您可以为此创建特征:
pub trait Comparator<T> {
fn compare(self, a: &T, b: &T) -> bool;
}
然后为每个比较器创建一个类型,例如Gt
:
struct Gt;
// You can also implement it individually for `String`, `f64` and `Vec<Value>`.
impl<T: PartialOrd> Comparator<T> for Gt {
fn compare(self, a: &T, b: &T) -> bool {
PartialOrd::gt(a, b)
}
}
然后:
fn apply_op<F>(v: &Value, compare_val: &Value, op: F) -> bool
where
F: Comparator<String> + Comparator<f64> + Comparator<Vec<Value>>,
{
match (v, compare_val) {
(Value::String(s), Value::String(compare_str)) => op.compare(s, compare_str),
(Value::Float(f), Value::Float(compare_f)) => op.compare(f, compare_f),
_ => false,
}
}
我想编写一些代码,这些代码在特定特征的实现者之间应该是通用的,但直到运行时才能知道其确切类型。
特别是,我想将 PartialOrd
中的函数应用于给定枚举中的部分案例。这是我要实现的基本版本:
enum Value {
String(String),
Float(f64),
Array(Vec<Value>),
}
fn apply_op<T, F>(v: &Value, compare_val: &Value, op: F) -> bool
where
F: FnOnce(&T, &T) -> bool,
T: PartialOrd,
{
match (v, compare_val) {
(Value::String(s), Value::String(compare_str)) => op(s, compare_str),
(Value::Float(f), Value::Float(compare_f)) => op(f, compare_f),
_ => false,
}
}
然后为 op
传入类似 PartialOrd::gt
的内容。
由于类型 T
由 match arm 确定,因此无法单态化,因此无法编译。
有没有办法解决这个问题,也许可以使用某种 trait/wrapper 结构骗局?
Playground link here,其中包括上面的版本(无法编译)和我目前用来解决这个问题的宏方法。宏没问题,不过真的感觉不用宏也可以。
您不能 late-bind 通用函数,但您可以为此创建特征:
pub trait Comparator<T> {
fn compare(self, a: &T, b: &T) -> bool;
}
然后为每个比较器创建一个类型,例如Gt
:
struct Gt;
// You can also implement it individually for `String`, `f64` and `Vec<Value>`.
impl<T: PartialOrd> Comparator<T> for Gt {
fn compare(self, a: &T, b: &T) -> bool {
PartialOrd::gt(a, b)
}
}
然后:
fn apply_op<F>(v: &Value, compare_val: &Value, op: F) -> bool
where
F: Comparator<String> + Comparator<f64> + Comparator<Vec<Value>>,
{
match (v, compare_val) {
(Value::String(s), Value::String(compare_str)) => op.compare(s, compare_str),
(Value::Float(f), Value::Float(compare_f)) => op.compare(f, compare_f),
_ => false,
}
}