fn 的可选通用类型参数?
Optional generic type Parameter for fn?
我想要一个函数有一个可选的通用类型参数来做这样的事情:
fn main() {
bar::<()>();
}
fn bar<F: Foo>() {
let x = some_computation();
if F != () {
let foo = F::new(x);
foo.foo();
}
}
trait Foo {
fn new(x: u64) -> Self;
fn foo(&self);
}
有没有办法拥有一个可选的类型参数?如果是这样,有没有办法检查类型参数是否存在于函数中?
我想答案是否定的,但是否可以使用宏来做到这一点?
您无法匹配类型本身,但从外观上看,您希望根据类型获得不同的功能。最好的方法是 impl Foo
用于您希望能够处理的任何类型。这是我对您的代码示例的解释:
fn main() {
let a = Bar::from(()).some_completion();
let b = Bar::from(1234).some_completion();
}
trait Foo {
fn some_completion(&self) -> Self;
}
struct Bar {}
impl From<u64> for Bar {
fn from(x: u64) -> Self {
todo!();
}
}
impl From<()> for Bar {
fn from(x: ()) -> Self {
todo!();
}
}
impl Foo for Bar {
fn some_completion(&self) -> Self {
Self { /* something different */ }
}
}
如果您确实需要泛型函数,std::str::parse
是一个很好的示例,说明如何传入类型(在本例中为数字类型)并更改 return 类型。
一般情况下,您不能为函数指定默认类型参数,并且除了通过 trait 上的方法外,您无法区分类型参数。
最简单的解决方法是只有两个函数,例如 bar
和 bar_with
,其中一个不接受类型参数,另一个接受一个类型参数:
// call with no type parameters
pub fn bar() {
let x = some_computation();
}
// call with type parameter
pub fn bar_with<F: Foo>() {
let x = some_computation();
let foo = F::new(x);
foo.foo();
}
如果函数足够复杂,您可以拥有一个两个函数都调用的私有辅助函数:
// call with no type parameters
pub fn bar() {
bar_inner(|_x| { /* do nothing */ })
}
// call with type parameter
pub fn bar_with<F: Foo>() {
bar_inner(|x| {
let foo = Foo::new(x);
foo.foo();
})
}
fn bar_inner<Func: FnOnce(u64)>(func: Func) {
let x = some_computation();
func(x);
}
或者,您可以使用针对所有 Foo
类型和默认类型 (()
) 实施的附加特征来解决此问题:
trait BarArg {
fn bar_inner(x: u64);
}
impl<F: Foo> BarArg for F {
fn bar_inner(x: u64) {
let foo = foo::new(x);
foo.foo();
}
}
impl BarArg for () {
fn bar_inner(_x: u64) {
// do nothing
}
}
fn bar<B: BarArg>() {
let x = some_computation();
B::bar_inner(x)
}
我现在知道了! :D
我可以提供 Foo
:
的 noop 实现
pub struct NoopFoo {}
impl Foo for NoopFoo {
fn new(_: u64) -> Self { NoopFoo {} }
fn foo(&self) {}
}
我仍然很好奇这是否可以用宏来解决...
我想要一个函数有一个可选的通用类型参数来做这样的事情:
fn main() {
bar::<()>();
}
fn bar<F: Foo>() {
let x = some_computation();
if F != () {
let foo = F::new(x);
foo.foo();
}
}
trait Foo {
fn new(x: u64) -> Self;
fn foo(&self);
}
有没有办法拥有一个可选的类型参数?如果是这样,有没有办法检查类型参数是否存在于函数中?
我想答案是否定的,但是否可以使用宏来做到这一点?
您无法匹配类型本身,但从外观上看,您希望根据类型获得不同的功能。最好的方法是 impl Foo
用于您希望能够处理的任何类型。这是我对您的代码示例的解释:
fn main() {
let a = Bar::from(()).some_completion();
let b = Bar::from(1234).some_completion();
}
trait Foo {
fn some_completion(&self) -> Self;
}
struct Bar {}
impl From<u64> for Bar {
fn from(x: u64) -> Self {
todo!();
}
}
impl From<()> for Bar {
fn from(x: ()) -> Self {
todo!();
}
}
impl Foo for Bar {
fn some_completion(&self) -> Self {
Self { /* something different */ }
}
}
如果您确实需要泛型函数,std::str::parse
是一个很好的示例,说明如何传入类型(在本例中为数字类型)并更改 return 类型。
一般情况下,您不能为函数指定默认类型参数,并且除了通过 trait 上的方法外,您无法区分类型参数。
最简单的解决方法是只有两个函数,例如 bar
和 bar_with
,其中一个不接受类型参数,另一个接受一个类型参数:
// call with no type parameters
pub fn bar() {
let x = some_computation();
}
// call with type parameter
pub fn bar_with<F: Foo>() {
let x = some_computation();
let foo = F::new(x);
foo.foo();
}
如果函数足够复杂,您可以拥有一个两个函数都调用的私有辅助函数:
// call with no type parameters
pub fn bar() {
bar_inner(|_x| { /* do nothing */ })
}
// call with type parameter
pub fn bar_with<F: Foo>() {
bar_inner(|x| {
let foo = Foo::new(x);
foo.foo();
})
}
fn bar_inner<Func: FnOnce(u64)>(func: Func) {
let x = some_computation();
func(x);
}
或者,您可以使用针对所有 Foo
类型和默认类型 (()
) 实施的附加特征来解决此问题:
trait BarArg {
fn bar_inner(x: u64);
}
impl<F: Foo> BarArg for F {
fn bar_inner(x: u64) {
let foo = foo::new(x);
foo.foo();
}
}
impl BarArg for () {
fn bar_inner(_x: u64) {
// do nothing
}
}
fn bar<B: BarArg>() {
let x = some_computation();
B::bar_inner(x)
}
我现在知道了! :D
我可以提供 Foo
:
pub struct NoopFoo {}
impl Foo for NoopFoo {
fn new(_: u64) -> Self { NoopFoo {} }
fn foo(&self) {}
}
我仍然很好奇这是否可以用宏来解决...