如何根据泛型类型是否实现特征以不同方式实现函数?

Kev*_*rez 5 generic-programming rust

我想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
}
Run Code Online (Sandbox Code Playgroud)

我认为这样做的一种方法是创建一个我们必须定义的特征do_something(&Self),但我不确定。我的代码片段是我将首先尝试的。

Cal*_*tor 7

这是基于夜间功能专业化的解决方案:

#![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
}
Run Code Online (Sandbox Code Playgroud)

第一步是创建一个 trait 来定义do_something(&self). 现在,我们为 定义impl了这个 trait 的两个s Foo<T>:一个impl为所有人实现的通用“父”T和一个专门impl为实现的子集T实现的“子” Debug。孩子impl可以专门研究父母的项目impl。我们要专门化的这些项目需要default在 parent中用关键字标记impl。在您的示例中,我们希望专门化do_something.