对std :: marker :: Sized的虚假要求

扬·胡德克(Jan Hudec)

更新:此更简单的代码(play)表现出相同的症状:

use std::fmt::Display;

pub fn arg(a: &str, b: &Display) {
}

fn main() {
    arg("foo", "bar");
}

给出错误:

<anon>:7:16: 7:21 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
<anon>:7     arg("foo", "bar");
                        ^~~~~
<anon>:7:16: 7:21 note: `str` does not have a constant size known at compile-time
<anon>:7     arg("foo", "bar");
                        ^~~~~

但是我没有任何理由在这里要求尺寸。ab被同等对待,他们是同一类型,也没有问题a所以

  • 为什么有问题b,和
  • 我该如何告诉我,特质不会有已知的身材。

实际上,这是一个特征类型,无论底层类型是什么,它都永远不会知道类型。那么为什么要尺寸呢?

哦,我不要忘记:在实际的用例中,我需要动态多态性。函数(方法)将与不同实际类型的参数和存储的引用链接在一起(请参见下面的原始展览),因此我无法将其转换为T: Trait + ?Sized


原始展览:

我有一些类似以下的代码(另请参见play.rust-lang.org):

pub trait Trait { /* some methods */ }

impl Trait for str { /* some implementation */ }

pub struct Struct<'a> {
    args: HashMap<&'a str, &'a Trait>,
}

impl<'a> Struct<'a> {
    pub fn new() -> Self {
        Struct { args: HashMap::new() }
    }

    pub fn arg(mut self, key: &'a str, value: &'a Trait) -> Struct<'a> {
        self.args.insert(key, value);
        return self;
    }

    // of course there is something to process the collected arguments too
}

fn main() {
    Struct::new().arg("foo", "bar");
}

这给了我错误:

test.rs:32:30: 32:35 error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
test.rs:32     Struct::new().arg("foo", "bar");
                                             ^~~~~
test.rs:32:30: 32:35 note: `str` does not have a constant size known at compile-time
test.rs:32     Struct::new().arg("foo", "bar");

克里斯·摩根

该错误不是伪造的。

特征对象的原始表示形式是(std::raw::TraitObject):

#[repr(C)]
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}

对象的实际数据在单个指针后面。

但是动态大小类型呢?以slice(&[T])为例,它们具有以下形式:

#[repr(C)]
pub struct Slice<T> {
    pub data: *const T,
    pub len: usize,
}

该参考是两个词:指向切片起点的指针切片中元素的数量

的大小&T因此实际上并不恒定如果TSized&T而且Box<T>将是一个词,但如果T不是Sized&T并且Box<T>2个字。

let word = std::mem::size_of::<usize>();

// References to sized types: one word.
assert_eq!(std::mem::size_of::<&()>(), 1 * word);
assert_eq!(std::mem::size_of::<&u8>(), 1 * word);
assert_eq!(std::mem::size_of::<&String>(), 1 * word);

// References to unsized types: two words.
assert_eq!(std::mem::size_of::<&[u8]>(), 2 * word);
assert_eq!(std::mem::size_of::<&str>(), 2 * word);
assert_eq!(std::mem::size_of::<&std::path::Path>(), 2 * word);

这有什么影响?好吧,如前所述,特征对象的定义要求数据指针只有一个字长。要存储一个动态大小的类型,在那里需要两个单词。我没有给过多考虑它是否会成为实用性可能膨胀的所有特质对象有两个数据字(其中之一将是大小的物体的情况下,多余的),所以它可能会,也可能不会,但是该语言已决定不支持动态大小类型的特征对象。

因此:如果要创建特征对象,则需要使用大小类型(例如)的对象&str,而不是动态大小类型(例如)的对象str这意味着(x: &&str) as &std::fmt::Display;

arg("foo", &"bar");

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

当我尝试在未确定大小的类型上手动实现Ord和Eq时,为什么不满足特征绑定[[T]:std :: marker :: Sized`的要求?

实现Read trait:trait绑定`std :: error :: Error +'static:std :: marker :: Sized`不满足

如何解决错误E0277:特质绑定`[usize]:std :: marker :: Sized`不满意?

'static:std :: marker :: Sized`不满意-我需要装箱吗?

当关联类型没有大小时,如何避免需要`std :: marker :: Sized`?

具有Sized上级特征的特征仍然具有错误“ std :: marker :: Sized不满意”

未為 Type 實現特徵 `std::marker::Copy`

没有为Foo实现core :: marker :: Sized

std :: condition_variable可预测的虚假唤醒?

std :: this_thread :: sleep_for()可以虚假唤醒吗?

c++11 std::notify_all 和虚假唤醒

Rust 2021 与 2018:特征 `std::marker::Send` 未实现 - 在 2021 版中执行此操作的正确方法是什么?

std :: vector :: erase的MoveAssignable要求与std :: vector :: emplace_back的MoveInsertable要求

关于严格排序,std :: map的compare参数有什么要求?

对std :: forward_list :: remove_if谓词的要求

为什么std :: queue要求元素是可复制的?

std :: unordered_set ::: reserve是否满足容器内存要求?

std :: forward_list和序列概念要求

std :: addressof是否否定了STL运算符和要求?

标准是否要求std :: tuple_size对SFINAE友好?

std :: search的C ++二进制谓词实现要求

GNUMakefile和gcc:解决冲突的“ -std = c ++”要求的顺序

android studio .cpp文件中的std :: string失败要求错误

std :: stack如何强制容器类满足某些要求

std::stable_sort 中 operator< constness 的要求

拖放Google Maps Marker

转换函数、std::is_base_of 和虚假的不完整类型:替换失败是一个错误

即使在要求提供指针时,`std::any_cast<T>` 是否要求 `T` 是可构造的?

Marker.remove(), Marker.setPosition 不起作用