“预期类型参数"通用结构的构造函数中的错误 [英] "Expected type parameter" error in the constructor of a generic struct

查看:23
本文介绍了“预期类型参数"通用结构的构造函数中的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将活塞纹理存储在结构中.

I am trying to store piston textures in a struct.

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 实现gfx::Resources 虽然(我认为这只是设备特定的实现.)我实际上并不关心这是什么类型,但我需要知道以便我可以将它存储在结构体.

gfx_device_gl::Resources implements gfx::Resources though (I think it's just the device specific implementation.) I don't actually care what type this is, but I need to know so that I can store it in the struct.

我在 Github 上制作了一个可编译存储库.

I made a compilable repo on Github.

(我怀疑 Rust 泛型/特征:"expected 'Foo<B>',发现 'Foo<Foo2>'" 是同一个问题,但我不知道如何将其应用于我的问题.)

(I suspect Rust generics/traits: "expected 'Foo<B>', found 'Foo<Foo2>'" is the same question, but I can't figure out how to apply it to my problem.)

推荐答案

这是您的错误的重现:

struct Foo<T> {
    val: T,
}

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

fn main() {}

问题出现是因为你试图对编译器撒谎.这段代码:

The problem arises because you tried to lie to the compiler. This code:

impl<T> Foo<T> {
    fn new() -> Self {
        /* ... */
    }
}

说对于调用者选择的任何T,我都会创建一个具有该类型的Foo".然后你的实际实现选择一个具体类型——在这个例子中,一个bool.不能保证 Tbool.请注意,您的 new 函数甚至不接受任何 T 类型的参数,这是非常值得怀疑的,因为这就是调用者在 99% 的情况下选择具体类型的方式.

Says "For whatever T the caller chooses, I will create a Foo with that type". Then your actual implementation picks a concrete type — in the example, a bool. There's no guarantee that T is a bool. Note that your new function doesn't even accept any parameter of type T, which is highly suspect as that's how the caller picks the concrete type 99% of the time.

正确的说法是

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

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

Although you probably want to pick a more specific name than new, as it looks as if you are trying to make your struct generic. Presumably there would be other constructors with different types.

对于您的确切代码,您可能需要类似

For your exact code, you probably want something like

impl TextureFactory<gfx_device_gl::Resources> { /* ... */ }

另一种可能的解决方案是从结构中删除泛型类型参数.如果您只使用 gfx_device_gl::Resources 构建它,那么没有理由将其设为通用.

Another possible solution would be to remove the generic type parameter from your struct. If you only ever construct it with a gfx_device_gl::Resources, then there's no reason to make it generic.

在其他情况下,您可能会尝试返回一个实现了 trait 的类型.为此,您可以使用装箱的 trait 对象:

In other cases, you may be trying to return a type that implements a trait. For that, you can use a boxed trait object:

impl Foo<Box<dyn std::fmt::Display>> {
    fn new() -> Self {
        Foo { val: Box::new(true) }
    }
}

在未来,您可能还可以使用 impl Trait(也称为 existential types):

In the future, you may also be able to use impl Trait (a.k.a. existential types):

#![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 }
    }
}

另见:

这篇关于“预期类型参数"通用结构的构造函数中的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆