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

Posted

技术标签:

【中文标题】泛型结构的构造函数中的“预期类型参数”错误【英文标题】:"Expected type parameter" error in the constructor of a generic struct 【发布时间】:2022-01-12 20:10:39 【问题描述】:

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

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>'" 是同一个问题,但我不知道如何将其应用于我的问题。)

【问题讨论】:

***.com/questions/31490913/… 或 ***.com/questions/31060851/… 的可能重复 您可以使用trait objects,来实现您的代码似乎涉及的那种多态性。 【参考方案1】:

这是您的错误的重现:

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 更具体的名称,但看起来您似乎正在尝试使您的结构通用。大概会有 other 不同类型的构造函数。

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

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

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

在其他情况下,您可能会尝试返回实现特征的类型。为此,您可以使用盒装 trait 对象:

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

【讨论】:

谢谢!我没有意识到我可以在impl 中“专门化”一些东西。

以上是关于泛型结构的构造函数中的“预期类型参数”错误的主要内容,如果未能解决你的问题,请参考以下文章

构造函数中的分段错误不明确

创建其构造函数需要参数的泛型类型的实例?

关于泛型

使用反射为泛型类创建构造函数

c#中泛型类构造函数重载赋值时为啥不接受null?对其赋空值应给怎么做?

Java:使用具有泛型构造函数的构建模式时“无法解析方法”