简体   繁体   English

泛型结构的构造函数中的“预期类型参数”错误

[英]"Expected type parameter" error in the constructor of a generic struct

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,
        }
    }
}

This does not compile:这不编译:

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

I made a compilable repo on Github .在 Github 上做了一个可编译的 repo

(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.) (我怀疑Rust 泛型/特征:“预期的 'Foo<B>', found 'Foo<Foo2>'”是同一个问题,但我不知道如何将其应用于我的问题。)

Here's a reproduction of your error:这是您的错误的再现:

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 {
        /* ... */
    }
}

Says "For whatever T the caller chooses, I will create a Foo with that type".说“对于调用者选择的任何T ,我都会创建一个具有该类型的Foo ”。 Then your actual implementation picks a concrete type — in the example, a bool .然后您的实际实现选择一个具体的类型——在示例中,一个bool There's no guarantee that T is a bool .不能保证Tbool 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.请注意,您的new函数甚至不接受任何类型的参数T ,这是非常值得怀疑的,因为这就是调用者在 99% 的情况下选择具体类型的方式。

The correct way of saying this would be正确的说法是

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

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.尽管您可能想选择一个比new更具体的名称,但看起来好像您正在尝试使您的结构通用。 Presumably there would be other constructors with different types.大概会有其他不同类型的构造函数。

For your exact code, you probably want something like对于您的确切代码,您可能想要类似的东西

impl TextureFactory<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.如果你只用gfx_device_gl::Resources构造它,那么没有理由让它通用。

In other cases, you may be trying to return a type that implements a trait.在其他情况下,您可能会尝试返回实现 trait 的类型。 For that, you can use a boxed trait object:为此,您可以使用装箱的 trait 对象:

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

In the future, you may also be able to use impl Trait (aka existential types ):将来,您还可以使用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 }
    }
}

See also:也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM