如何解决赋值时的“预期结构,找到类型参数”?

Kru*_*rum 2 rust

几天前刚开始使用 Rust。我现在正在移植一些 C++ 代码,这个问题似乎与常见的“预期结构,获取类型”排序相反。该代码涉及两个类,容器类A和客户端类B。

use std::vec::Vec;

struct  A<T:FooTrait> {
    children: Vec<*mut T>
}

impl <T:FooTrait> A<T> {
    fn insert(&mut self, val: &mut T) -> Handle<T> {
        self.children.push(val);
        return Handle{owner: self};
    }
}
struct B {
    handle: Handle<B>
}

trait FooTrait {
    fn set_handle<T:FooTrait>(&mut self, h: Handle<T>);
}

impl FooTrait for B {
    fn set_handle<B:FooTrait>(&mut self, h: Handle<B>) {
        self.handle = h;  // <-- Here is the problem
    }
}

struct  Handle<T:FooTrait> {
    owner: *mut A<T>
}

impl <T:FooTrait> Default for Handle<T> {
    fn default()->Handle<T> {
        Handle {
            owner: std::ptr::null_mut()
        }
    }
}
fn main() {
    let mut foo =  A::<B> { children: Default::default() };
    let mut b = B{handle: Default::default()};
    b.handle = foo.insert(&mut b);
}
Run Code Online (Sandbox Code Playgroud)

得到错误:

error[E0308]: mismatched types
  --> src/main.rs:23:23
   |
22 |     fn set_handle<B:FooTrait>(&mut self, h: Handle<B>) {
   |                   - this type parameter
23 |         self.handle = h;
   |                       ^ expected struct `B`, found type parameter `B`
   |
   = note: expected struct `Handle<B>` (struct `B`)
              found struct `Handle<B>` (type parameter `B`)
Run Code Online (Sandbox Code Playgroud)

Cer*_*rus 5

简化版本(游乐场)

use std::marker::PhantomData;

struct B {
    handle: PhantomData<B>,
}

trait FooTrait {
    fn set_handle<T: FooTrait>(&mut self, h: PhantomData<T>);
}

impl FooTrait for B {
    fn set_handle<BType: FooTrait>(&mut self, h: PhantomData<BType>) {
        self.handle = h;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我已经更改了 中类型参数的名称set_handle。现在错误更加清晰了:

error[E0308]: mismatched types
  --> src/lib.rs:13:23
   |
12 |     fn set_handle<BType: FooTrait>(&mut self, h: PhantomData<BType>) {
   |                   ----- this type parameter
13 |         self.handle = h;
   |                       ^ expected struct `B`, found type parameter `BType`
   |
   = note: expected struct `std::marker::PhantomData<B>`
              found struct `std::marker::PhantomData<BType>`
Run Code Online (Sandbox Code Playgroud)

在您的情况下,错误本质上是相同的,因为通用参数是一种新类型,它掩盖了全局struct B.

现在,该怎么办?这取决于你想得到什么。

  • 如果struct B定义正确并且set_handle只需要处理s,只需从( playgroundB )中删除泛型参数即可:set_handle
trait FooTrait {
    fn set_handle(&mut self, h: PhantomData<B>);
}

impl FooTrait for B {
    fn set_handle(&mut self, h: PhantomData<B>) {
        self.handle = h;
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 如果struct B定义正确,但set_handle必须能够根据 不同的处理程序类型使用不同的处理程序类型Self,请使用关联的类型(playground):
trait FooTrait {
    type T: FooTrait;
    fn set_handle(&mut self, h: PhantomData<Self::T>);
}

impl FooTrait for B {
    type T = B;
    fn set_handle(&mut self, h: PhantomData<B>) {
        self.handle = h;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,实现块将选择它将获得哪种参数(处理程序,在您的情况下)。

  • 如果set_handle定义正确,即调用者可以选择处理程序的类型,那么struct B也必须是通用的。然而,在这种情况下,您基本上不能使用基于特征的方法,因为特征也必须是通用的,并且您将无法在不提供参数的情况下简单地在任何通用绑定中使用它(参数也必须绑定) ,无穷无尽)。