- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
这是拍摄 out of context所以看起来有点奇怪,但我有以下数据结构:
use std::marker::PhantomData;
pub struct Map<T, M=()> {
data: Vec<T>,
_marker: PhantomData<fn(M) -> M>,
}
Map
是一个关联映射,其中键被“标记”以防止在另一个不相关的映射上使用来自一个映射的键。用户可以通过传递他们制作的一些独特类型作为 M
来选择加入此功能,例如:
struct PlayerMapMarker;
let mut player_map: Map<String, PlayerMapMarker> = Map::new();
这一切都很好,但是我想为这个 map 编写的一些迭代器(例如只给出值的迭代器)在它们的类型中不包含标记。下面的转化可以安全地丢弃标记吗?
fn discard_marker<T, M>(map: &Map<T, M>) -> &Map<T, ()> {
unsafe { std::mem::transmute(map) }
}
这样我就可以编写和使用:
fn values(&self) -> Values<T> {
Values { inner: discard_marker(self).iter() }
}
struct Values<'a, T> {
inner: Iter<'a, T, ()>,
}
最佳答案
长话短说: 添加 #[repr(C)]
你应该很好。
这里有两个不同的问题:转换在返回类型返回有效数据的意义上是否有效,以及整个事情是否违反了可能附加到所涉及类型的任何更高级别的不变量。 (在我的 blog post 的术语中,您必须确保保持有效性和安全不变性。)
对于有效性不变量,您处于未知领域。编译器可以决定布局 Map<T, M>
与 Map<T, ()>
截然不同,即 data
字段可能处于不同的偏移量并且可能存在虚假填充。这似乎不太可能,但到目前为止我们在这里保证很少。关于我们可以和想要保证的内容的讨论happening right now .我们有意避免对 repr(Rust)
做出太多保证。以免把自己逼到墙角。
你可以做的是添加 repr(C)
到你的结构,那么我相当确定你可以指望 ZST 不会改变任何东西(但我 asked for clarification 只是为了确定)。对于 repr(C)
我们为结构的布局提供了更多保证,这实际上是它的全部目的。如果您想玩弄结构布局,您可能应该添加该属性。
对于更高级别的安全不变量,您必须小心不要创建损坏的 Map
并让那个“泄漏”超出你的 API 的边界(进入周围的安全代码),即你不应该返回 Map
的实例。这违反了您可能对其施加的任何不变量。此外,PhantomData
对方差和下降检查器有一些影响,你应该知道。由于正在转换的类型是如此微不足道(您的标记类型不需要删除,即它们和它们的传递字段都没有实现 Drop
)我认为您不必从这方面期待任何问题。
要清楚,repr(Rust)
(默认值)也可能很好,一旦我们决定这是我们想要保证的东西——并且忽略 size-0-align-1 类型(如 PhantomData
)对我来说完全是一个非常明智的保证。虽然我个人仍然建议使用 repr(C)
除非这有你不愿意支付的成本(例如,因为你失去了编译器通过重新排序自动减少大小并且无法手动复制它)。
关于rust - 转化 PhantomData 标记安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52911942/
我有一个看起来像这样的特质: trait Handler { fn handle(&self, msg: &Message, connection: &mut C); } 实例应该被链接起来,
阅读时the answer for another question , 我看到了这个结构 [1]: struct Clipboard { marker: PhantomData, } 虽然我
我正在尝试开发一种批处理系统。在其中我想使用某种 Process 结构,它拥有所有与流程相关的部分。当前的实现使用 PhantomData 来强制执行类型约束: pub struct Process,
我想创建一个通用元组结构 Producer可以容纳任何类型 P它实现了特征 Produce ,定义如下。这会产生(预期的)注释错误: trait Produce { fn get(&mut s
这是拍摄 out of context所以看起来有点奇怪,但我有以下数据结构: use std::marker::PhantomData; pub struct Map { data: Vec
我发现 PhantomData 的概念在 Rust 中相当困惑。我在基于 FFI 的代码中广泛使用它来限制对象的生命周期,但我仍然不确定我是否正确地执行了此操作。 这是我经常最终使用它的人为示例。例如
我的结构包含不安全代码和指向另一种结构的原始可变指针。不安全结构只能在另一个结构的生命周期内使用,但不能为指针指定生命周期。我发现 std::marker::PhantomData 可以用于这个未使用
我在查看一些 Rust 源代码时发现了一种名为 PhantomData 的数据类型。我正在浏览 Rust 文档并在互联网上搜索了很多。但是,我无法理解这种数据类型在 rust 中的实际用途。如果可能的
PhantomData与 Copy 互动以一种令人惊讶的方式: use std::marker::PhantomData; #[derive(Copy, Clone)] pub struct Seco
我知道下面的代码是 hacky,但它可以被称为安全和惯用的 Rust 吗?有更好的方法吗? // needs to do 'rustup default nightly' to run under v
This question already has answers here: Why is it useful to use PhantomData to inform the compiler t
在 Rustonomicon's guide to PhantomData ,有一部分是关于如果 Vec 会发生什么-like struct 有 *const T字段,但没有 PhantomData
我正在尝试创建一种类型,它通过网络发送和接收数据并将字节序列化/反序列化为声明的类型。为此,我一直在使用 PhantomData输入 std .但是,我最近遇到了一种情况,我想让我的方法采用 &mut
在this question有人评论说您可以使用 PhantomData 添加绑定(bind)到结构内原始指针的生命周期。我想我会尝试在我一直在处理的现有代码段上执行此操作。 这是我们的(最小化)起点
我知道 PhantomData旨在使用数据类型定义中的生命周期或类型参数,否则这些参数将不会被使用。我最近在查看 Rc 的定义在Rust std lib并注意到它似乎使用了 PhantomData ,
这个问题在这里已经有了答案: Deriving a trait results in unexpected compiler error, but the manual implementation
我是一名优秀的程序员,十分优秀!