如何根据泛型类型是否实现特征来不同地实现函数? [英] How can I implement a function differently depending on if a generic type implements a trait or not?
问题描述
我想根据通用类型T
是否实现Debug
来使do_something
的实现成为条件.有什么办法可以做这样的事吗?
I'd like to make the implementation of do_something
conditional based on if the generic type T
implements Debug
or not. Is there any way to do something like this?
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)
的特征,但是我不确定.我的代码段是我将首先尝试的.
I think one way to do this is to create a trait where we have to define do_something(&Self)
, but I'm not sure. My code snippet is what I will try first.
推荐答案
以下是基于夜间功能的解决方案 专业化 :
Here is a solution based on the nightly feature 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
实现的通用父级" impl
和仅对以下子集实现的专用子级" impl
T
实现Debug
.子级impl
可能会专门处理父级impl
中的项目.我们要专门处理的这些项目需要在父impl
中用default
关键字标记.在您的示例中,我们要专门研究do_something
.
The first step is to create a trait which defines do_something(&self)
. Now, we define two impl
s of this trait for Foo<T>
: a generic "parent" impl
which is implemented for all T
and a specialized "child" impl
which is only implemented for the subset where T
implements Debug
. The child impl
may specialize items from the parent impl
. These items we want to specialize need to be marked with the default
keyword in the parent impl
. In your example, we want to specialize do_something
.
这篇关于如何根据泛型类型是否实现特征来不同地实现函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!