22

私は現在、C++ メモリ編集ライブラリを作成しており、読み取り/書き込み API には型特性 (std::is_pod、std::is_same) と boost::enable_if を使用して 3 つのオーバーロードを提供しています。

  1. ポッドの種類。例 MyMem.Read(SomeAddress);
  2. 文字列型。例 MyMem.Read>(SomeAddress); (これは実際には C++ 文字列を読み取るのではなく、C スタイルの文字列を読み取り、それを C++ 文字列に変換します。)
  3. ベクトル型。例 MyMem.Read>(SomeAddress, NumElem); (これは実際にベクトルを読み取るのではなく、C スタイルの配列を読み取ってベクトルに変換します。)

オーバーロード 2 と 3 は、オーバーロード 1 の単純な「ラッパー」です。

最近、コンパイル時に読み書きしたいデータのサイズを知っていたので、一連の読み取りと書き込みに std::array を使用したいと思いました (私は PE ファイル形式のラッパーを書いていました)。

std::array を使用するコードを作成し、std::array 型の検出と処理のために別のオーバーロードを追加するつもりでしたが、誤ってコンパイルを実行してしまい、驚いたことにそれが機能しました!

私は現在 MSVC 10 を使用していますが、std::array の場合、T が POD の場合、std::array は POD であることがわかります。(つまり、オーバーロード 1 を使用するだけで機能します。)

私の質問は、これが C++ 標準によって保証されているのか、それとも実装に任されているのかということです。

自分で標準を確認できることはわかっていますが、このサイトの言語弁護士の一部を信頼するほど自分自身を信頼していないため、「セカンドオピニオン」を取得するのが最善であると考えました. ;)

ありがとう

PS コードはこちらから入手できます (ヘッダーのみのライブラリです): http://code.google.com/p/hadesmem/source/browse/trunk/HadesMem-v2/Hades-Memory/Hades-Memory/MemoryMgr.h#86

4

3 に答える 3

14

§23.3.1:

配列は、次の構文で初期化できる集約 (8.5.1) ですarray a<T, N> = { initializer-list }; 。ここで、initializer-list は、型が T に変換可能な最大 N 個の要素のコンマ区切りのリストです。

C++03 では、POD は集約に関して定義されていました。つまり、すべてのサブオブジェクトがネイティブであるクラス、または集約が POD であるクラスです。したがって、下位互換性により、C++0xstd::arrayは POD です。

または、最終的には、§9/5 (自明なクラスを定義する) 9/6 (標準レイアウトを定義する) および 9/9 (先行する要件を POD に結合する) の箇条書きを 8.5.1/ の箇条書きと比較することができます。 1、集計を定義します。

8.5.1:

集合体は、ユーザー提供のコンストラクター (12.1)、非静的データ メンバーのブレースまたはイコール初期化子 (9.2)、プライベートまたは保護された非静的データ メンバー (条項 11)、基本クラスなし (条項 10)、および仮想関数なし (10.3)。

実際、要素タイプも POD であり、実装が仕様に加えてまたは内部でarray宣言しない限り、箇条 9 の要件がカバーされます。operator=movearray

本当にアナルになるために、17.5.2.2は言います

  1. 説明のために、条項 18 から 30 および付属書 D では、コピー/移動コンストラクタ、代入演算子、または (非仮想) デストラクタについて、デフォルトで生成できるものと同じ見かけのセマンティクス (12.1、12.4、12.8 )。
  2. 実装が、そのようなメンバー関数の署名、またはデフォルトで生成できる仮想デストラクタの明示的な定義を提供するかどうかは指定されていません。

擬似コードの注記template class array

// No explicit construct/copy/destroy for aggregate type

(割り当て) または? がconstruct/copy/destroy含まれますか? おそらくそうあるべきですが、厳密に読むとそうではないと思います。operator=move

Johannesが言及しているように、これはPOD性だけでなく、些細なコピー可能性にも「影響する」ことに注意してください。

于 2010-09-09T08:02:04.083 に答える
8

POD の定義によると:

9クラス

9 POD 構造体は、自明クラス標準レイアウト クラスの両方であり、非 POD 構造体、非 POD 共用体 (またはそのような型の配列) 型の非静的データ メンバーを持たないクラスです。同様に、POD 共用体は自明クラスと標準レイアウト クラスの両方である共用体であり、型非 POD 構造体、非 POD 共用体 (またはそのような型の配列) の非静的データ メンバーはありません。POD クラスは、POD 構造体または POD 共用体のいずれかであるクラスです。

【地雷強調】

std::array単純な標準レイアウト クラス テンプレートであるというすべての要件を満たしています。したがって、あなたの質問に対する答えはイエスです。

于 2010-09-09T06:58:45.757 に答える
1

Potatoswatter は、私の結論に誤りを見つけました。C++ では、実装が "同じ見かけのセマンティクスで" 代入演算子を明示的に定義することを明示的に許可しています。これにより、自明ではないコピー可能なタイプになります。コミュニティ wiki にする...


PODnes に対してテストするのではなく、 trivially copyable に対してテストしたくないようです。これは、制限がはるかに少ないです。memcpyそれが、や友人と一緒に使用できる C++0x 制約タイプの方法だからです。

また、 の POD 性についての保証はないと思いますが、以下に示すように、自明なコピー可能性についての保証はあります (結論に誤りがない場合) std::array。私たちが知っているように、 は集合体であり、集合体はstd::array

集合体は、ユーザー提供のコンストラクター (12.1)、非静的データ メンバーのブレースまたはイコール初期化子 (9.2)、プライベートまたは保護された非静的データ メンバー (条項 11)、基本クラスなし (条項 10)、および仮想関数なし (10.3)。

自明にコピー可能性は、クラスを持つクラスに対して定義されていますが、

  • 重要なコピー コンストラクターがない (12.8)。
  • 自明でない移動コンストラクターを持たない (12.8)、
  • 重要なコピー代入演算子を持たない (13.5.3, 12.8),
  • 自明でない移動代入演算子がない (13.5.3、12.8)、および
  • 自明なデストラクタがあります (12.4)。

std::arrayデストラクタはありません(の定義のコメントのようにstd::array)。std::arrayのクラス定義のコメントがそれを主張しているにもかかわらず、これは集約クラスの定義から従うようには見えません。

残りの 4 つの要件は、集約のこれら 4 つの特別なメンバー関数のベース、仮想関数、およびユーザー提供のバージョンがないことから生じます。

于 2010-09-09T19:26:00.037 に答える