【问题标题】:Conditionally implement a Rust trait only if a type constraint is satisfied仅在满足类型约束时有条件地实现 Rust 特征
【发布时间】:2017-12-30 21:16:59
【问题描述】:

我有以下结构:

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())
    }
}

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

是否可以在 Rust 中指定“条件实现”,当且仅当满足某些泛型类型 trait 约束时我们才实现 trait?如果不满足约束,则目标 trait(在这种情况下为 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));
}

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、具体问题或错误以及在问题本身中重现它所需的最短代码 - 此代码甚至不是语法上有效的 Rust 代码,因此它会因语法错误而失败。此外,您还没有包含完整的错误消息,因此我们不知道您可能遇到了什么错误。
  • @Shepmaster 我很抱歉。事后看来,这个问题并没有经过深思熟虑。我已经修改了语法错误并为问题添加了额外的说明。我已选择 Kornel 的帖子作为接受的答案,但还将编辑原始问题帖子以确认使用我指定的代码确实可行。
  • 我已更新问题以包含对@Kornel 答案的额外解释。

标签: rust generic-programming


【解决方案1】:

对于这个特定的实例,derive(Default) 提供的实现完全符合您的要求:

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

另见:

【讨论】:

    【解决方案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

    【讨论】:

      【解决方案3】:

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

      Default trait 仅在 T 满足定义 Default 的实现时指定的类型约束时为 struct Foo&lt;T&gt; 实现。在这种情况下,约束被定义为where T: Default。因此,Foo&lt;T&gt; 仅在 T 实现 Default 时才实现 Default

      如上面的fn main() 示例所示,当T 未实现Default 时,任何尝试使用Foo&lt;T&gt;Default 实现都会产生编译器错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-15
        • 2019-09-19
        • 1970-01-01
        • 2020-12-24
        • 2019-12-17
        • 2021-01-28
        • 1970-01-01
        相关资源
        最近更新 更多