当前位置: 首页 > 知识库问答 >
问题:

在使用关联类型的情况下,如何实现泛型容器的借用?

竺焕
2023-03-14

我想为用户友好数据结构实现借用,以提供对函数中的内部_数据字段的访问,该字段对于数据提供程序来说应该是不可知的。internal_data字段的类型由traitTraitA关联的类型确定。请注意,密封的特性确保这里的这些特性都不能被其他板条箱实现;这是我严格提供的功能。此外,类型TraitA::Data受到空traitDataTrait的限制,以防止UserFriendlyDataStructure用作该类型。

以下示例最能说明问题:

use std::borrow::Borrow;
use std::marker::PhantomData;

mod private {
    pub trait Sealed {}
}

pub trait DataTrait: private::Sealed {}

pub trait TraitA: private::Sealed {
    type Data: DataTrait;
}

pub struct UserFriendlyDataStructure<A: TraitA> {
    internal_data: A::Data,
    _a: PhantomData<A>,
}

impl<A: TraitA> Borrow<A::Data> for UserFriendlyDataStructure<A> {
    fn borrow(&self) -> &A::Data {
        &self.internal_data
    }
}

pub fn important_function<A: TraitA, T: Borrow<A::Data>>(data: &T) {
    let _internal_data = data.borrow();
    // Do lots of work.
}

#[cfg(test)]
mod tests {
    use super::*;

    pub struct TestData(u32);

    impl super::private::Sealed for TestData {}

    impl DataTrait for TestData {}

    pub struct TestProvider;

    impl super::private::Sealed for TestProvider {}

    impl TraitA for TestProvider {
        type Data = TestData;
    }

    #[test]
    fn basic_test() {
        let ufds: UserFriendlyDataStructure<TestProvider> = UserFriendlyDataStructure {
            internal_data: TestData(100),
            _a: PhantomData::default(),
        };

        important_function::<TestProvider, _>(&ufds);
    }
}

不幸的是,编译器抱怨道:

error[E0119]: conflicting implementations of trait `std::borrow::Borrow<UserFriendlyDataStructure<_>>` for type `UserFriendlyDataStructure<_>`:
  --> src/lib.rs:19:1
   |
19 | impl<A: TraitA> Borrow<A::Data> for UserFriendlyDataStructure<A> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T> std::borrow::Borrow<T> for T
             where T: ?Sized;

有没有办法实现我的目标?

共有1个答案

荀辰钊
2023-03-14

通过引入冗余的第二个类型参数,可以诱使编译器接受代码,该参数被约束为与a::Data相同:

impl<A, D> Borrow<D> for UserFriendlyDataStructure<A>
where
    A: TraitA<Data = D>,
    D: DataTrait,
{
    fn borrow(&self) -> &A::Data {
        &self.internal_data
    }
}

我不知道为什么会这样,而简单地约束A::Data:DataTrait就不行了。我认为编译器应该接受这两个版本。

(操场上的完整代码

编辑:我们需要上面代码中的冗余类型D,这似乎是当前编译器实现的一个缺点,希望在编译器中集成实验类型推理引擎粉笔后得到解决。

 类似资料:
  • 我是Spring的新手,我正在尝试自动连接一个通用DAO。不幸的是,我遇到了一个错误。我试图根据它搜索信息,但大多数解决方案都声明使用@Qualifier注释,我认为这与我想要实现的目标背道而驰。 所以下面的一些代码(我将摆脱类参数,一旦我处理当前问题): 道 服务 和下面抛出的错误:

  • 问题内容: 我有课 和班级 关键是该方法不安全,因为我可以提供的项目与当前报告无关,但与其他报告相关,编译器不会抱怨。 是否可以用类型安全的方式编写该方法,即我们可以仅将T作为当前报表的类型作为参数传递。 问题答案: 我认为您正在寻找以下内容。 它的工作方式是: 您想用从 您要确保所有列表都属于同一类型 为了将参数绑定到从扩展的对象,您需要对自身进行参数化: 您添加需要从报表扩展的绑定 但是您要

  • 问题内容: 我知道Go将来不会有泛型,并且有一些建议可以用其他结构代替它们。但是在下面的例子中,我陷入了困境。 您可能会猜到,我试图使任何错误均告失败,并且希望将任何返回两个结果的函数放到第二个错误中。这工作正常,但丢失了它的类型信息,并且结果中只是一个空接口。 由于我也正在调用lib函数,因此我看不到使用Interfaces或Reflection解决此问题的方法。 有任何想法吗?我是完全走错了道

  • 编译时,此代码将产生以下+错误: 问题是访问中的类型T与列表中的T不相同。如何修复此编译问题?

  • 我在我的一个实用程序类中有一个方法,它接受一个集合和一个类对象,并返回一个Iterable实例,该实例可以遍历作为指定类实例的集合的所有成员。其签名为: 这对于大多数用例都非常有效,但现在我需要将其与泛型类

  • 这个问题是在泛型关联类型在Rust中可用之前提出的,尽管它们是被提出和开发的。 我的理解是,特征泛型和关联类型在它们可以绑定到结构的类型数量上有所不同。 关联类型仅绑定1个类型: 泛型关联类型是这两种类型的混合。它们绑定到一个类型,正好有一个关联的生成器,而生成器又可以关联任何数量的类型。那么前面示例中的和这个泛型关联类型有什么区别呢?