如何根据泛型类型是否实现特征来不同地实现函数? [英] How can I implement a function differently depending on if a generic type implements a trait or not?

查看:50
本文介绍了如何根据泛型类型是否实现特征来不同地实现函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想根据通用类型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 impls 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆