仅在满足类型约束时才有条件地实现Rust特征

时间:2017-12-30 21:16:59

标签: rust generic-programming

我有以下结构:

pub struct Foo<T> {
    some_value: T,
}

impl<T> Foo<T> {
    pub fn new(value: T) -> Self {
        Self { some_value: value }
    }
}

// Implement `Default()`, assuming that the underlying stored type
// `T` also implements `Default`.
impl<T> Default for Foo<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

如果Foo::default()实施T,我希望Default可用,但可用。

是否可以在Rust中指定“条件实现”,当且仅当满足某些泛型类型特征约束时才实现特征?如果不满足约束,则不实现目标特征(在这种情况下为Default)并且没有编译器错误。

换句话说,是否可以通过以下方式使用上面的通用结构?

fn main() {
    // Okay, because `u32` implements `Default`.
    let foo = Foo::<u32>::default();

    // This should produce a compiler error, because `Result` does not implement
    // the `Default` trait.
    //let bar = Foo::<Result<String, String>>::default();

    // This is okay. The `Foo<Result<...>>` specialisation does not implement
    // `Default`, but we're not attempting to use that trait here.
    let bar = Foo::<Result<u32, String>>::new(Ok(42));
}

3 个答案:

答案 0 :(得分:3)

对于此特定情况,derive(Default)提供的实施完全符合您的要求:

#[derive(Default)]
pub struct Foo<T> {
    some_value: T,
}

另见:

答案 1 :(得分:2)

在修复次要语法问题之后,您的示例确实有效:

pub struct Foo<T> {
    some_value: T,
}

impl<T> Foo<T> {
    pub fn new(value: T) -> Self {
        Self { some_value: value }
    }
}

// Implement `Default()`, assuming that the underlying stored type
// `T` also implements `Default`.
impl<T> Default for Foo<T>
where
    T: Default,
{
    fn default() -> Self {
        Self::new(T::default())
    }
}

fn main() {}

Playground

答案 2 :(得分:0)

正如@Kornel的回答所指出的,结果是编译器已经有条件地实现了泛型结构的特征。

如果Default满足在定义struct Foo<T>的实现时指定的类型约束,则T特征仅针对Default实施。在这种情况下,约束被定义为where T: Default。因此,如果Foo<T>实施Default,则T仅实施Default

如上面的fn main()示例所示,当Foo<T>未实现Default时,任何尝试使用T的{​​{1}}实现都会产生编译器错误。