我想根据通用类型do_something
是否实现T
来使Debug
的实现成为条件。有什么办法可以做这样的事情吗?
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)
的特征,但我不确定。我的代码段是我首先尝试的。
答案 0 :(得分:3)
以下是基于夜间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)
的特征。现在,我们为impl
定义了两个Foo<T>
的特征:为所有impl
实现的通用“父” T
和专门的“子” {{1 }}仅针对其中impl
实现T
的子集实现。子级Debug
可以专门处理父级impl
的项目。我们要专门处理的这些项目需要在父impl
中用default
关键字标记。在您的示例中,我们要专门研究impl
。