generics - 通用结构的构造函数中的“Expected type parameter”错误

标签 generics rust traits

我试图将 Piston 纹理存储在结构中。

struct TextureFactory<R> where R: gfx::Resources {
    block_textures: Vec<Rc<Texture<R>>>,
}

impl<R> TextureFactory<R> where R: gfx::Resources  {
    fn new(window: PistonWindow) -> Self {
        let texture = Rc::new(gfx_texture::Texture::from_path(
            &mut *window.factory.borrow_mut(),
            "assets/element_red_square.png",
            Flip::None, &TextureSettings::new()
        ).unwrap());
        let block_textures = Vec::new();
        block_textures.push(texture);

        TextureFactory {
            block_textures: block_textures,
        }
    }
}

这不会编译:

src/main.rs:37:9: 39:10 error: mismatched types:
 expected `TextureFactory<R>`,
    found `TextureFactory<gfx_device_gl::Resources>`
(expected type parameter,
    found enum `gfx_device_gl::Resources`)
gfx_device_gl::Resources implements gfx::Resources (我认为这只是特定于设备的实现。)我实际上并不在乎这是什么类型,但是我需要知道以便可以将其存储在结构中。

我做了一个compilable repo on Github

(我怀疑Rust generics/traits: "expected 'Foo<B>', found 'Foo<Foo2>'"是同一个问题,但我不知道如何将其应用于我的问题。)

最佳答案

这是您的错误的再现:

struct Foo<T> {
    val: T,
}

impl<T> Foo<T> {
    fn new() -> Self {
        Foo { val: true }
    }
}

fn main() {}

出现问题是因为您试图欺骗编译器。这段代码:
impl<T> Foo<T> {
    fn new() -> Self {
        /* ... */
    }
}

说:“对于调用者选择的T,我将创建该类型的Foo”。然后,您的实际实现选择了一个具体的类型-在示例中为bool。不能保证Tbool。请注意,您的new函数甚至不接受T类型的任何参数,这非常值得怀疑,因为这是调用者99%的时间选择具体类型的方式。

正确的说法是
impl Foo<bool> {
    fn new() -> Self {
        Foo { val: true }
    }
}

尽管您可能想选择一个比new更具体的名称,但看起来好像您正在尝试使结构通用。大概会有其他具有不同类型的构造函数。

对于您的确切代码,您可能想要类似
impl TextureFactory<gfx_device_gl::Resources> { /* ... */ }

另一个可能的解决方案是从您的结构中删除泛型类型参数。如果仅使用gfx_device_gl::Resources构造它,则没有理由使其通用。

在其他情况下,您可能试图返回实现特征的类型。为此,您可以使用装箱的特征对象:
impl Foo<Box<dyn std::fmt::Display>> {
    fn new() -> Self {
        Foo { val: Box::new(true) }
    }
}

将来,您也许还可以使用impl Trait(又称存在类型):
#![feature(type_alias_impl_trait)]

struct Foo<T> {
    val: T,
}

type SomeConcreteButOpaqueType = impl std::fmt::Display;

impl Foo<SomeConcreteButOpaqueType> {
    fn new() -> Self {
        Foo { val: true }
    }
}

也可以看看:
  • What is the correct way to return an Iterator (or any other trait)?
  • 关于generics - 通用结构的构造函数中的“Expected type parameter”错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63908576/

    相关文章:

    c++ - 如何在不知道类型的情况下声明模板指针?

    generics - 将函数作为参数传递时,如何遵守生命周期限制?

    design-patterns - Groovy 中@Delegate、@Mixin 和 Traits 的区别?

    variables - 将 "mut"放在变量名之前和 ":"之后有什么区别?

    scala - 在类构造函数中使用特征方法

    C++ - 知道类型/类是否嵌套?

    java - 在 java 中创建一个用户定义的类,就像 Integer/String 类

    c# - C#泛型类型中静态字段的初始化

    java - 更改泛型的空数组时出现意外的空指针异常

    rust - Rust 如何强制/实现 RAII