class 是否需要是标准布局类型才能确定其成员的内存偏移量?
Does a class need to be a standard layout type to be sure of the memory offsets of its members?
假设我想写一个侵入式列表。我有一个侵入式列表 class 模板,它采用类型和指向成员的指针用作节点。它看起来大致是这样的:
// This needs to be a member of anything the intrusive list is going to store.
class IntrusiveListNode {
// ...
}
// The intrusive list itself
template <class T, IntrusiveListNode T::*Member>
class IntrusiveList {
// ...
};
// This is a type that is going to be stored in an intrusive list.
class IntegerListNode {
public:
IntrusiveListNode node;
private:
int value;
};
// An example of the how the list would be used.
IntrusiveList<IntegerListNode, &IntegerListNode::node> myList;
您要存储在列表中的每个东西都有一个 IntrusiveListNode。要将该 IntrusiveListNode 变回您可以使用的东西,例如 IntegerListNode,您可以调用一个函数,该函数根据节点在 class 中的偏移量对节点执行一些指针运算,然后将其转换为适当的类型。这似乎有效,但我认为不能保证。
我希望能够向我的 class 添加一个 static_assert 以在编译时验证您使用的类型是安全的,但我不确定是什么static_assert的条件是。我 认为 这只有在持有 IntrusiveListNode 的类型是标准布局时才能保证有效 class,但我不确定,因为标准布局类型的要求似乎比我其实需要。
特别是,标准布局类型要求所有成员都具有相同的访问控制。我需要的是能够确保指针算法能够工作。这意味着你不能在多态类型上使用它,因为结构的两个不同版本可能有不同的布局,但如果该类型混合了私有和 public 数据成员,这应该不是问题, 正确的?如果我只要求类型是非多态的,会安全吗?或者有更好的检查吗?还是我一直在做 is_standard_layout
检查?
我不能在这方面引用标准(而且我很确定这是未定义的行为领域),但您通常可以依赖数据成员相对于指向包含 [ 的指针的偏移量的一致性=21=],前提是这个指针的静态类型是常量(在你的例子中是 IntegerListNode*)。
您可能会发现在测量偏移量时相对于派生类型的指针会发生变化,但只要您总是先 reinterpret_cast 到 IntegerListNode 然后才 static/dynamic 转换为派生类型如果需要输入,我几乎会觉得舒服 :)
这并不是说这是个好主意。实现侵入式列表不需要这样的指针算法。如果您只是在 IntegerListNode 中定义一个 "next" and/or "previous" 指针(指向一个 IntegerListNode),您可以将它的指向成员的指针传递给 IntrusiveList,并且永远不需要创意转化 :)
假设我想写一个侵入式列表。我有一个侵入式列表 class 模板,它采用类型和指向成员的指针用作节点。它看起来大致是这样的:
// This needs to be a member of anything the intrusive list is going to store.
class IntrusiveListNode {
// ...
}
// The intrusive list itself
template <class T, IntrusiveListNode T::*Member>
class IntrusiveList {
// ...
};
// This is a type that is going to be stored in an intrusive list.
class IntegerListNode {
public:
IntrusiveListNode node;
private:
int value;
};
// An example of the how the list would be used.
IntrusiveList<IntegerListNode, &IntegerListNode::node> myList;
您要存储在列表中的每个东西都有一个 IntrusiveListNode。要将该 IntrusiveListNode 变回您可以使用的东西,例如 IntegerListNode,您可以调用一个函数,该函数根据节点在 class 中的偏移量对节点执行一些指针运算,然后将其转换为适当的类型。这似乎有效,但我认为不能保证。
我希望能够向我的 class 添加一个 static_assert 以在编译时验证您使用的类型是安全的,但我不确定是什么static_assert的条件是。我 认为 这只有在持有 IntrusiveListNode 的类型是标准布局时才能保证有效 class,但我不确定,因为标准布局类型的要求似乎比我其实需要。
特别是,标准布局类型要求所有成员都具有相同的访问控制。我需要的是能够确保指针算法能够工作。这意味着你不能在多态类型上使用它,因为结构的两个不同版本可能有不同的布局,但如果该类型混合了私有和 public 数据成员,这应该不是问题, 正确的?如果我只要求类型是非多态的,会安全吗?或者有更好的检查吗?还是我一直在做 is_standard_layout
检查?
我不能在这方面引用标准(而且我很确定这是未定义的行为领域),但您通常可以依赖数据成员相对于指向包含 [ 的指针的偏移量的一致性=21=],前提是这个指针的静态类型是常量(在你的例子中是 IntegerListNode*)。
您可能会发现在测量偏移量时相对于派生类型的指针会发生变化,但只要您总是先 reinterpret_cast 到 IntegerListNode 然后才 static/dynamic 转换为派生类型如果需要输入,我几乎会觉得舒服 :)
这并不是说这是个好主意。实现侵入式列表不需要这样的指针算法。如果您只是在 IntegerListNode 中定义一个 "next" and/or "previous" 指针(指向一个 IntegerListNode),您可以将它的指向成员的指针传递给 IntrusiveList,并且永远不需要创意转化 :)