如何根据泛型类型是否实现特征来不同地实现函数?
How can I implement a function differently depending on if a generic type implements a trait or not?
我想根据通用类型 T
是否实现 Debug
来使 do_something
的实现成为有条件的。有没有办法做这样的事情?
struct A(i32);
#[derive(Debug)]
struct B(i32);
struct Foo<T> {
data: T,
/* more fields */
}
impl<T> Foo<T> {
fn do_something(&self) {
/* ... */
println!("Success!");
}
fn do_something(&self)
where
T: Debug,
{
/* ... */
println!("Success on {:?}", self.data);
}
}
fn main() {
let foo = Foo {
data: A(3), /* ... */
};
foo.do_something(); // should call first implementation, because A
// doesn't implement Debug
let foo = Foo {
data: B(2), /* ... */
};
foo.do_something(); // should call second implementation, because B
// does implement Debug
}
我认为一种方法是创建一个特征,我们必须在其中定义 do_something(&Self)
,但我不确定。我的代码片段是我首先要尝试的。
这是一个基于夜间功能的解决方案 specialization:
#![feature(specialization)]
use std::fmt::Debug;
struct A(i32);
#[derive(Debug)]
struct B(i32);
struct Foo<T> {
data: T,
/* more fields */
}
trait Do {
fn do_something(&self);
}
impl<T> Do for Foo<T> {
default fn do_something(&self) {
/* ... */
println!("Success!");
}
}
impl<T> Do for Foo<T>
where
T: Debug,
{
fn do_something(&self) {
/* ... */
println!("Success on {:?}", self.data);
}
}
fn main() {
let foo = Foo {
data: A(3), /* ... */
};
foo.do_something(); // should call first implementation, because A
// doesn't implement Debug
let foo = Foo {
data: B(2), /* ... */
};
foo.do_something(); // should call second implementation, because B
// does implement Debug
}
第一步是创建定义 do_something(&self)
的特征。现在,我们为 Foo<T>
定义了此特征的两个 impl
:一个为所有 T
实现的通用 "parent" impl
和一个专门的 "child" impl
仅针对 T
实现 Debug
的子集实现。子 impl
可以专门化父 impl
的项目。这些我们要专门化的项目需要在父impl
中用default
关键字标记。在您的示例中,我们想要专门化 do_something
.
我想根据通用类型 T
是否实现 Debug
来使 do_something
的实现成为有条件的。有没有办法做这样的事情?
struct A(i32);
#[derive(Debug)]
struct B(i32);
struct Foo<T> {
data: T,
/* more fields */
}
impl<T> Foo<T> {
fn do_something(&self) {
/* ... */
println!("Success!");
}
fn do_something(&self)
where
T: Debug,
{
/* ... */
println!("Success on {:?}", self.data);
}
}
fn main() {
let foo = Foo {
data: A(3), /* ... */
};
foo.do_something(); // should call first implementation, because A
// doesn't implement Debug
let foo = Foo {
data: B(2), /* ... */
};
foo.do_something(); // should call second implementation, because B
// does implement Debug
}
我认为一种方法是创建一个特征,我们必须在其中定义 do_something(&Self)
,但我不确定。我的代码片段是我首先要尝试的。
这是一个基于夜间功能的解决方案 specialization:
#![feature(specialization)]
use std::fmt::Debug;
struct A(i32);
#[derive(Debug)]
struct B(i32);
struct Foo<T> {
data: T,
/* more fields */
}
trait Do {
fn do_something(&self);
}
impl<T> Do for Foo<T> {
default fn do_something(&self) {
/* ... */
println!("Success!");
}
}
impl<T> Do for Foo<T>
where
T: Debug,
{
fn do_something(&self) {
/* ... */
println!("Success on {:?}", self.data);
}
}
fn main() {
let foo = Foo {
data: A(3), /* ... */
};
foo.do_something(); // should call first implementation, because A
// doesn't implement Debug
let foo = Foo {
data: B(2), /* ... */
};
foo.do_something(); // should call second implementation, because B
// does implement Debug
}
第一步是创建定义 do_something(&self)
的特征。现在,我们为 Foo<T>
定义了此特征的两个 impl
:一个为所有 T
实现的通用 "parent" impl
和一个专门的 "child" impl
仅针对 T
实现 Debug
的子集实现。子 impl
可以专门化父 impl
的项目。这些我们要专门化的项目需要在父impl
中用default
关键字标记。在您的示例中,我们想要专门化 do_something
.