Use trait object to pass str in rust

与世无争的帅哥 提交于 2019-12-24 00:59:26

问题


I'm reading a rust book and is confused by one example here.

use std::fmt::Display;

fn main() {
    test("hello");
    test2("hello")
}

fn test(s: &dyn Display) {
    println!("{}", s);
}

fn test2(s: &str) {
    println!("{}", s);
}

Here passing &'static str as a trait object failed. It complains that "hello" does not have a fixed size at compile time while it is a pointer type. Yet the second call works: why?


回答1:


&dyn Display expects a reference. You feed it a &str. So the compiler legitimately thinks that the type that implements Display is str. Hence, it complains that is does not have a fixed sized.

Add a reference, and it works fine:

use std::fmt::Display;

fn main() {
    test(&"hello");
}

fn test(s: &dyn Display) {
    println!("{}", s);
}



回答2:


str does implement Display, but it is not possible to coerce a &str to a &dyn Display because the implementation of Display for str may (and does) use the string's length. Length is part of the type &str but not part of the type &dyn Display, and you can't discard the length because that would make it impossible to implement Display at all.

Another way to look at this is that a vtable (virtual method table) does not exist for the implementation of Display for str, because vtables may only contain functions that accept thin self pointers, but in impl Display for str, &self is a fat pointer. See also Why can't `&(?Sized + Trait)` be casted to `&dyn Trait`?

However, &str itself also implements Display, so you can make test work by simply adding another layer of indirection, as Boiethios's answer shows.



来源:https://stackoverflow.com/questions/57817405/use-trait-object-to-pass-str-in-rust

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!