< 返回版块

leolee0101 发表于 2022-08-03 19:31

下面的 std 库 中 struct NodeRef 为什么用 PhantomData ?

https://github.com/rust-lang/rust/blob/19abca1172ae10d5c084b6c3013d92680f92dd8b/library/alloc/src/collections/btree/node.rs

  pub struct NodeRef<BorrowType, K, V, Type> {
    /// The number of levels that the node and the level of leaves are apart, a
    /// constant of the node that cannot be entirely described by `Type`, and that
    /// the node itself does not store. We only need to store the height of the root
    /// node, and derive every other node's height from it.
    /// Must be zero if `Type` is `Leaf` and non-zero if `Type` is `Internal`.
    height: usize,
    /// The pointer to the leaf or internal node. The definition of `InternalNode`
    /// ensures that the pointer is valid either way.
    node: NonNull<LeafNode<K, V>>,
    _marker: PhantomData<(BorrowType, Type)>,
}

    pub struct Immut<'a>(PhantomData<&'a ()>);
    pub struct Mut<'a>(PhantomData<&'a mut ()>);
    pub struct ValMut<'a>(PhantomData<&'a mut ()>);
    pub enum Owned {}
    pub enum Dying {}
	
    pub enum Leaf {}
    pub enum Internal {}
    pub enum LeafOrInternal {}

impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>{...}	

BorrowType 可以是 (Immut<'a>,Mut<'a>,Owned,Dying)其中之一。

Type 可以是 (Leaf,Internal,LeafOrInternal) 其中之一。

NodeRef 没有 impl Drop ,应该跟 dropck 没关系。

如果仅仅是防止出现unused type(lifetime) parameter,由于 两个 类型参数 对应的具体类型都是空的,不用 PhantomData 而真正使用(BorrowType, Type) ,是否一样?

评论区

写评论
Grainspring 2022-08-03 22:26

嗯,也是zero。哪作用可能用在variance或其他auto traits上啦。

👇
leolee0101: 空enum 和 只有PhantomData的struct 是不是 zero-sized?

--
👇
Grainspring: 直接换成 (BorrowType, Type),就占用大小了呀。。。PhantomData<(BorrowType, Type)>是zero-sized.

--
👇
leolee0101: 这个我明白。注释是说 impl 的时候 根据类型参数的特化版本,实现不同的函数。不懂的地方是,struct NodeRef 声明里 PhantomData<(BorrowType, Type)> 直接换成 (BorrowType, Type) 是不是也是一样。这里的 PhantomData 有什么特别作用。

--
👇
Grobycn: 就在你贴出来的代码片段上面, 给出的文档就有说明:

/// Both `BorrowType` and `NodeType` restrict what methods we implement
作者 leolee0101 2022-08-03 22:16

空enum 和 只有PhantomData的struct 是不是 zero-sized?

--
👇
Grainspring: 直接换成 (BorrowType, Type),就占用大小了呀。。。PhantomData<(BorrowType, Type)>是zero-sized.

--
👇
leolee0101: 这个我明白。注释是说 impl 的时候 根据类型参数的特化版本,实现不同的函数。不懂的地方是,struct NodeRef 声明里 PhantomData<(BorrowType, Type)> 直接换成 (BorrowType, Type) 是不是也是一样。这里的 PhantomData 有什么特别作用。

--
👇
Grobycn: 就在你贴出来的代码片段上面, 给出的文档就有说明:

/// Both `BorrowType` and `NodeType` restrict what methods we implement
Grainspring 2022-08-03 22:10

直接换成 (BorrowType, Type),就占用大小了呀。。。PhantomData<(BorrowType, Type)>是zero-sized.

--
👇
leolee0101: 这个我明白。注释是说 impl 的时候 根据类型参数的特化版本,实现不同的函数。不懂的地方是,struct NodeRef 声明里 PhantomData<(BorrowType, Type)> 直接换成 (BorrowType, Type) 是不是也是一样。这里的 PhantomData 有什么特别作用。

--
👇
Grobycn: 就在你贴出来的代码片段上面, 给出的文档就有说明:

/// Both `BorrowType` and `NodeType` restrict what methods we implement
作者 leolee0101 2022-08-03 22:07

这个我明白。注释是说 impl 的时候 根据类型参数的特化版本,实现不同的函数。不懂的地方是,struct NodeRef 声明里 PhantomData<(BorrowType, Type)> 直接换成 (BorrowType, Type) 是不是也是一样。这里的 PhantomData 有什么特别作用。

--
👇
Grobycn: 就在你贴出来的代码片段上面, 给出的文档就有说明:

/// Both `BorrowType` and `NodeType` restrict what methods we implement
Grainspring 2022-08-03 22:05

https://doc.rust-lang.org/stable/reference/special-types-and-traits.html?highlight=PhantomData#phantomdata

phantomdata that is considered to own a T for the purposes of variance, drop check, and auto traits.

它会拥有T的variance、drop check、autotraits的特性。。比如:若T:!Send,则phantomdata:!send

Grobycn 2022-08-03 21:47

就在你贴出来的代码片段上面, 给出的文档就有说明:

/// Both `BorrowType` and `NodeType` restrict what methods we implement
作者 leolee0101 2022-08-03 21:10

意思是说 NodeRef 结构声明中,直接去掉 PhantomData 。

--
👇
Neutron3529: 你准备怎么直接使用BorrowType?

不定义到结构体里面你根本用不了。

Neutron3529 2022-08-03 20:34

你准备怎么直接使用BorrowType?

不定义到结构体里面你根本用不了。

Easonzero 2022-08-03 19:46

我觉得是一样的, 使用PhantomData可能更多的是从可读性角度考虑的

1 共 9 条评论, 1 页