< 返回版块

laizy 发表于 2020-10-02 12:46

下面的代码是从tantivy源码里摘出来的,对T: Tokenizer + Clone,实现TokenizerClone,而Tokenizer本身有 TokenizerClone 的约束,这不就死循环了嘛?为啥能编译通过?

pub trait Tokenizer: 'static + Send + Sync + TokenizerClone {
    /// Creates a token stream for a given `str`.
    fn token_stream<'a>(&self, text: &'a str) -> BoxTokenStream<'a>;
}

pub trait TokenizerClone {
    fn box_clone(&self) -> Box<dyn Tokenizer>;
}

impl<T: Tokenizer + Clone> TokenizerClone for T {
    fn box_clone(&self) -> Box<dyn Tokenizer> {
        Box::new(self.clone())
    }
}

按我的思路只能写出下面的代码,尽管能工作,但api体验没上面的好:用户定义的结构需要derive(Clone)和实现TokenizerBase,但使用时用Tokenizer;而用上面的方式实现和使用都是Tokenizer,甚至有可能可以将TokenizerClone设置为私有,减小api surface。

pub trait TokenizerBase: 'static + Send + Sync   {
    /// Creates a token stream for a given `str`.
    fn token_stream<'a>(&self, text: &'a str) -> BoxTokenStream<'a>;
}

pub trait Tokenizer: TokenizerBase {
    fn box_clone(&self) -> Box<dyn Tokenizer>;
}

impl<T:TokenizerBase + Clone> Tokenizer for T {
    fn box_clone(&self) -> Box<dyn Tokenizer> {
        Box::new(self.clone())
    }
}

评论区

写评论
whfuyn 2020-10-02 22:42

能通过编译是因为这两个都只是约束吧,只要同时提供两者的实现就能满足了。虽然我也觉得有点迷惑。

--
👇
whfuyn: 这能不能看作是在表达trait A和trait B必须同时实现?

whfuyn 2020-10-02 22:20

这能不能看作是在表达trait A和trait B必须同时实现?

1 共 2 条评论, 1 页