“Expected type parameter” error in the constructor of a generic struct

后端 未结 1 582
一向
一向 2020-11-22 04:55

I am trying to store piston textures in a struct.

struct TextureFactory where R: gfx::Resources {
    block_textures: Vec&         


        
相关标签:
1条回答
  • 2020-11-22 05:44

    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". 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.

    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. 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.

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

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

    See also:

    • What is the correct way to return an Iterator (or any other trait)?
    0 讨论(0)
提交回复
热议问题