1

押し付けがましいリストを書きたいとしましょう。ノードとして使用するメンバーへの型とポインターを受け取る侵入型のリスト クラス テンプレートがあります。おおよそ次のようになります。

// 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 のように使用できるものに戻すには、クラス内のオフセットに基づいてノードでポインタ演算を行う関数を呼び出し、それを適切な型にキャストします。これは機能しているように見えますが、保証されていないと思います。

使用している型が安全であることをコンパイル時に検証するクラスに static_assert を追加できるようにしたいのですが、static_assert の条件がどうなるかわかりません。これは、IntrusiveListNode を保持する型が標準レイアウト クラスである場合にのみ機能することが保証されていると思いますが、標準レイアウト型の要件は実際に必要以上に厳しいように見えるため、確信が持てません。

特に、標準レイアウト タイプでは、すべてのメンバーが同じアクセス コントロールを持つ必要があります。私が必要としているのは、ポインター演算が機能することを確認できることだけです。つまり、構造体の 2 つの異なるバージョンが異なるレイアウトになる可能性があるため、ポリモーフィック型でこれを使用できないことを意味しますが、型にプライベート データ メンバーとパブリック データ メンバーが混在している場合、これは問題になりませんよね? 型が非ポリモーフィックであることを要求しただけで安全でしょうか? または、行うべきより良いチェックがありますか?それとも、私はis_standard_layoutチェックをしているのですか?

4

1 に答える 1

1

これに関する標準を引用することはできません (そして、これは undefined-behavior-land であると確信しています) が、一般に、含まれているクラスへのポインターに対するデータ メンバーのオフセットの一貫性を信頼できます。このポインタの型は一定です(あなたの場合は IntegerListNode* )。

派生型へのポインターと比較してオフセットを測定すると、オフセットが変化することに気付くかもしれませんが、常に最初に IntegerListNode に再解釈_キャストし、必要に応じて派生型に静的/動的にキャストする限り、ほとんど快適に感じるでしょう。 :)

これが良い考えだと言っているわけではありません。このようなポインター演算は、侵入型リストを実装するために必要ではありません。IntegerListNode (IntegerListNode を指す) で「次へ」および/または「前へ」のポインターを定義するだけの場合、そのメンバーへのポインターを IntrusiveList に渡すことができ、創造的な変換が必要になることはありません :)

于 2015-05-26T06:03:24.977 に答える