【问题标题】:Rust generics - traits, structs and associated typesRust 泛型 - 特征、结构和关联类型
【发布时间】:2022-11-23 20:18:30
【问题描述】:

我来自 C++ 社区,切换到 Rust...,并使用 rust-generics,任何人都可以解释为什么我在这个虚拟示例中收到此错误吗?谢谢你。

    struct FF<T1,T2>(T1,T2);

    trait FFt<T1,T2>{
        type t1 = T1;
        type t2 = T2;
        fn call<t1,t2>(&self, Self::t1, Self::t2);
    };

    impl<T1,T2> FFt<T1,T2> for FF<T1,T1> {
        fn call<T1,T2>(&self, t_1: Self::t1, t_2: Self::t2) {
            t_1.a = 1;
            t_2.b = 1;
        }
    }

    struct AA{
        a:i32,
        b:i32,
    }
    let fff : FF<AA,AA> = FF(AA{a:0,b:0},AA{a:0,b:0});

    fff.call(AA{a:0,b:0},AA{a:0,b:0}); // <----- ERROR LINE !!!

错误

error[E0609]: no field `a` on type `T1`
   --> p2p/./src/lib.rs:172:17
    |
170 |     impl<T1,T2> FFt<T1,T2> for FF<T1,T1> {
    |          -- type parameter 'T1' declared here
171 |         fn call<T1,T2>(&self,t_1 : Self::t1,t_2 : Self::t2) {
172 |             t_1.a = 1;
    |                 ^

error[E0609]: no field `b` on type `T2`
   --> p2p/./src/lib.rs:173:17
    |
170 |     impl<T1,T2> FFt<T1,T2> for FF<T1,T1> {
    |             -- type parameter 'T2' declared here
...
173 |             t_2.b = 1;
    |                 ^

【问题讨论】:

  • 因为FFt类型中的T1、T2类型是任何类型的占位符。不知道 a 或 b 字段是否真的存在于具体类型中。例如,如果我输入 FF&lt;u32, u32&gt; 会怎样?
  • 假设你做了let fff: FF&lt;i32, i32&gt; = FF(1, 2); fff.call(3, 4);没有4.b的1.a可以访问。如果您需要访问结构的特定字段,则需要通过通过方法公开该字段的特征来绑定泛型类型,或者不使用泛型,而是使用要使用的特定类型。
  • 在这方面,Rust 与 C++ 的行为不同:C++ 允许你“去看看你能走多远”,基本上是鸭式输入,看看模板参数是否有成员 a。另一方面,Rust 要求您指定要对泛型类型执行的操作。 AFAIK 无法指定类型将具有成员 a - 相反,您可能希望具有可能具有 fn a() -&gt; i32 的特征,然后调用 a(),您在 C++ 中只需访问成员 @987654334 @.

标签: generics rust


【解决方案1】:

您可能想阅读 rust 书,因为您的开端并不好。

任何人都可以解释为什么我在这个虚拟示例中收到此错误吗?

因为 C++ 泛型和 Rust 泛型的工作原理完全不同。

C++ 模板将被类型替换然后检查,因此只要您传递适合所用内容的类型,它就会起作用。

Rust 泛型基于约束,它们独立于实例化进行类型检查,并且仅在约束允许的范围内工作。约束指定为低谷特质.我听说过 C++概念尽管我在那里没有经验,但工作方式类似。

在这里,您的泛型类型不受约束,因此就编译器而言,它们是无法,编译器几乎只会假定它们是Sized。此外,特征不支持字段。

还

trait FFt<T1,T2>{
        type t1 = T1;
        type t2 = T2;

这没有多大意义,泛型类型参数的意义在于呼叫者决定它是什么,关联类型的要点是实施者决定它是什么(但每个实现只能有一个)。

接着

        fn call<t1,t2>(&self, Self::t1, Self::t2);

这意味着call有两个通用参数t1和t2(不正确的命名约定),它们也是不受约束的,并且完全独立于T1/T2和FFt::t1/FFt::t2。所以此时您有 6 种不同的未知、不受约束和不相关的类型。

【讨论】:

  • 太好了谢谢。解释被接受!
猜你喜欢
  • 2020-01-03
  • 2023-01-12
  • 1970-01-01
  • 2020-03-31
  • 2022-07-31
  • 1970-01-01
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
相关资源
最近更新 更多