如何根据泛型类型是否实现特征来不同地实现函数?

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.