Generics 由另一个参数限定的泛型参数
我正在写一个模拟框架。为此,我需要接受一个函数,该函数可以用作另一个函数的替换,并将其存储。我当前的设计通过强制相同的输入和输出类型来实现这一点,但在强制正确的生命周期时完全失败 相反,我需要编写一个通用函数,它接受一个基函数及其替换:Generics 由另一个参数限定的泛型参数,generics,rust,traits,Generics,Rust,Traits,我正在写一个模拟框架。为此,我需要接受一个函数,该函数可以用作另一个函数的替换,并将其存储。我当前的设计通过强制相同的输入和输出类型来实现这一点,但在强制正确的生命周期时完全失败 相反,我需要编写一个通用函数,它接受一个基函数及其替换: fn main() { selector(foo, baz, "local", false); selector(bar, baz, "local", false); selector(foo, bar, "local", false);
fn main() {
selector(foo, baz, "local", false);
selector(bar, baz, "local", false);
selector(foo, bar, "local", false); // SHOULD FAIL, bar is NOT substitute of foo
}
fn foo(_: &str) -> &'static str {
"foo"
}
fn bar(s: &str) -> &str {
s
}
fn baz(_: &str) -> &'static str {
"baz"
}
// DOES NOT COMPILE
// fn selector<U, V, F: Fn(U) -> V, G: F>(base: F, subs: G, arg: U, use_base: bool) -> V {
// match use_base {
// true => base(arg),
// false => subs(arg),
// }
// }
// COMPILES, but is too weak
fn selector<U, V, F: Fn(U) -> V, G: Fn(U) -> V>(base: F, subs: G, arg: U, use_base: bool) -> V {
match use_base {
true => base(arg),
false => subs(arg),
}
}
baz
是foo
和bar
的替代品,因为它返回的字符串既可以用来代替静态的
字符串,也可以依赖于借用bar
不是foo
的替代品,因为借用的值不能代替的静态值
我想创建这样的东西,但它无法编译:
// FAILURE
// V
fn selector<U, V, F: Fn(U) -> V, G: F>(base: F, subs: G) {...}
//失败
//五
fn选择器V,G:F>(基:F,子:G){…}
问题是我无法表达F
和G
之间的关系。Rust似乎没有混凝土类型的超类型概念。Rust也知道类型的这些“兼容性”:都是关于。诀窍是使两个参数具有相同的类型,至少就函数而言是如此
让我们先试试更简单的方法:
// Both arguments have the same type (including the same lifetime)
fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
x
}
let outer = 3;
{
let inner = 27;
println!("{}", foo(&outer, &inner));
}
如果我们这样尝试,不幸的是仍然会得到一个错误:“预期的fn项,发现了不同的fn项”。这与“函数项与函数指针”问题有关。你可以了解更多关于这方面的信息。遗憾的是,在这种情况下,对函数指针的强制并没有起作用,因此一种方法是显式地强制转换函数:
type FnStatic = fn(&str) -> &'static str;
type FnWeaker = fn(&str) -> &str;
selector(foo as FnStatic, baz as FnStatic, "local", false);
selector(bar as FnWeaker, baz as FnStatic, "local", false);
selector(foo as FnStatic, bar as FnWeaker, "local", false);
()
这实际上和预期的一样:前两个调用很好,但第三个错误是:
错误[E0308]:类型不匹配
-->src/main.rs:7:31
|
7 |选择器(foo为FnStatic,条形图为FnStatic,“本地”,错误);
|^^^^^^^^^^^^^^^^^^^^^^^^^^预期的混凝土寿命,找到绑定的寿命参数
|
=注意:预期类型为`for&str`
为&'r str找到类型``
然而,在调用站点显式转换函数类型仍然有点难看。不幸的是,我还没有找到一个方法来隐藏这一点。我尝试编写一个强制强制执行强制的宏,但当函数指针具有不同类型(包括第二个示例)时,该宏不起作用
fn selector<U, V, F: Fn(U) -> V>(base: F, subs: F, arg: U, use_base: bool) -> V {
match use_base {
true => base(arg),
false => subs(arg),
}
}
type FnStatic = fn(&str) -> &'static str;
type FnWeaker = fn(&str) -> &str;
selector(foo as FnStatic, baz as FnStatic, "local", false);
selector(bar as FnWeaker, baz as FnStatic, "local", false);
selector(foo as FnStatic, bar as FnWeaker, "local", false);