簡體   English   中英

泛型錯誤:期望的類型參數,找到結構

[英]Generics Error: expected type parameter, found struct

我開始了一個新項目,我希望盡可能模塊化,我的意思是我希望將來可以替換其他部分。 這似乎是一個完美的使用traits ,在現階段,我有這樣的代碼:

mod parser;
mod renderer;
mod renderers;

use parser::MarkParser;
use renderer::MarkRenderer;

struct Rustmark <P: MarkParser, R: MarkRenderer> {
    parser: P,
    renderer: R,
}


impl <P: MarkParser, R: MarkRenderer> Rustmark <P, R> {
    fn new() -> Rustmark <P, R> {
        Rustmark {
            parser: parser::DefaultParser::new(),
            renderer: renderers::HTMLRenderer::new(),
        }
    }

    fn render(&self, input: &str) -> &str {
        self.renderer.render(self.parser.parse(input))
    }
}

但是我得到了一些錯誤,主要是這個錯誤:

錯誤:類型不匹配:預期Rustmark<P, R> ,找到Rustmark<parser::DefaultParser, renderers::html::HTMLRenderer> (期望的類型參數,找到struct parser::DefaultParser )[E0308]

還有一些像這樣的生命周期錯誤:

錯誤:由於需求沖突,無法推斷自動強制的適當生命周期

help:考慮使用如下所示的顯式生命周期參數: fn parse<'a>(&'a self, input: &'a str) -> &str

我嘗試了多次調整以使其工作,但它們似乎都沒有安撫編譯器。 所以我想知道這是否是正確的方法以及我能做些什么才能使它發揮作用。

第一個錯誤:使用DefaultParser類型的字段parserHTMLRenderer類型的字段renderer創建Rustmark對象,但該函數應返回Rustmark <P, R> 通常,P不是DefaultParser類型,R不是HTMLRenderer類型,因此它永遠不會編譯。 如果您想要具有正確類型的默認值,那么一個好的解決方案是綁定PR以實現Default trait ,這樣:

use std::default:Default;

impl <P: MarkParser + Default, R: MarkRenderer + Default> Rustmark <P, R> {
    fn new() -> Rustmark <P, R> {
        Rustmark {
            parser: P::default(),
            renderer: R:default(),
        }
    }
}

第二個錯誤:主要問題是你返回一個可能會在render方法中死掉的引用(你可能在內部render方法中分配的String )。 編譯器告訴您它不知道該引用指向的對象的生命周期,因此無法保證該引用有效。 您可以指定一個生命周期參數,但在您的情況下,最好的解決方案可能是返回String對象本身,而不是引用。

根據Andrea P的回答,我在std中查找了default特征。 其定義如下:

pub trait Default {
    fn default() -> Self;
}

我最終做的不是使用default特征,而是在我的MarkParserMarkRenderer特征中添加一個構造函數 new ,如下所示:

pub trait MarkParser {
    fn new() -> Self;
    fn parse(&self, input: &str) -> &str;
}

我不知道的關鍵部分是Self關鍵字,這樣我就可以編寫我的實現:

impl <P: MarkParser, R: MarkRenderer> Rustmark <P, R> {
    fn new() -> Rustmark <P, R> {
        Rustmark {
            parser: P::new(),
            renderer: R::new(),
        }
    }

    fn render(&self, input: &str) -> &str {
        self.renderer.render(self.parser.parse(input))
    }
}

這也正是同樣的事情,執行Default特質,除了我可以使用new的,而不是default ,我更喜歡我沒有到添加Default性狀的impl RustMark的。

impl <P: MarkParser, R: MarkRenderer> Rustmark <P, R> {

代替

impl <P: MarkParser + Default, R: MarkRenderer + Default> Rustmark <P, R> {

非常感謝Andrea P指出我正確的方向。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM