POD¶
POD (Plain Old Data) とは C と ABI 互換性が保証されるデータ構造のことです。
データ構造が POD であるかは std::is_pod で判定することができます。
std::is_pod
を使用するには <type_traits>
のインクルードが必要です。
データ構造を POD にしたい場合には static_assert
で保証するとよいです。
#include <type_traits>
struct FundamentalTypes {
int16_t i;
double d;
};
static_assert(std::is_pod<FundamentalTypes>::value, "Should be POD.");
基本型¶
基本型は POD です。
enum Direction {
kLeft,
kRight,
kBoth
};
static_assert(std::is_pod<char>::value, "Should be POD.");
static_assert(std::is_pod<int32_t>::value, "Should be POD.");
static_assert(std::is_pod<double>::value, "Should be POD.");
static_assert(std::is_pod<Direction>::value, "Should be POD.");
配列¶
POD の配列は POD です。
static_assert(std::is_pod<int[2]>::value, "Should be POD.");
POD の std::array
も POD ですが、
POD の std::vector
は POD ではありません。
static_assert(std::is_pod<std::array<int, 2>>::value, "Should be POD.");
static_assert(std::is_pod<std::vector<int>>::value, "Should be POD."); // failed
参照型¶
参照型は POD ではありません。
static_assert(std::is_pod<int&>::value, "Should be POD."); // failed
ポインタ型¶
あらゆるポインタは POD です。 POD ではない型に対するポインタも POD です。
static_assert(std::is_pod<int*>::value, "Should be POD.");
// std::vector<int> は POD ではないが std::vector<int>* は POD
static_assert(std::is_pod<std::vector<int>*>::value, "Should be POD.");
構造体¶
構造体の条件は複雑なため、本書では簡単な例だけを紹介します。
POD の要件
トリビアルかつスタンダードレイアウトである場合に POD となります。 詳細は以下を参照してください。
POD になる構造体の例¶
以下の条件をすべて満たす構造体は POD です。
- 継承していない
- メンバ関数を持たない (暗黙的に定義される特別なメンバ関数は明示しない)
- すべてのデータメンバは POD
- データメンバに対するアクセス指定子が1種類のみ (暗黙的な
public
指定も含む)
// データメンバを持たない
struct Empty {};
static_assert(std::is_pod<Empty>::value, "Should be POD.");
// すべてのデータメンバが基本型
struct FundamentalTypes {
int16_t i;
double d;
};
static_assert(std::is_pod<FundamentalTypes>::value, "Should be POD.");
POD の構造体は入れ子にすることができます。
// POD の構造体 FundamentalTypes をデータメンバにもつ
struct FundamentalTypesAsChild {
char c;
FundamentalTypes f;
};
static_assert(std::is_pod<FundamentalTypesAsChild>::value, "Should be POD.");
// POD の構造体 FundamentalTypesAsChild をデータメンバにもつ
struct FundamentalTypesAsGrandchild {
char c;
FundamentalTypesAsChild f;
};
static_assert(std::is_pod<FundamentalTypesAsGrandchild>::value,
"Should be POD.");
POD にならない構造体の例¶
暗黙的に定義される特別なメンバ関数をユーザ定義¶
ユーザ定義のデフォルトコンストラクタをもつ構造体は POD ではありません。
struct UserDefinedDefaultConstructor {
UserDefinedDefaultConstructor() {}
};
static_assert(std::is_pod<UserDefinedDefaultConstructor>::value,
"Should be POD."); // failed
default
指定であれば POD になります。
struct DefaultConstructorAsExplicitDefault {
DefaultConstructorAsExplicitDefault() = default;
};
static_assert(std::is_pod<DefaultConstructorAsExplicitDefault>::value,
"Should be POD.");
デフォルトコンストラクタ以外の 暗黙的に定義される特別なメンバ関数についても同様です。
仮想関数¶
仮想関数をもつ構造体は POD ではありません。
struct VirtualFunction {
virtual void Hoge() {}
};
static_assert(std::is_pod<VirtualFunction>::value, "Should be POD."); // failed
非 POD のデータメンバ¶
POD ではない型の非 static
データメンバを持つ構造体は POD ではありません。
struct NonPodMemberVariable {
std::vector<int> v; // std::vector<int> は POD ではない
};
static_assert(std::is_pod<NonPodMemberVariable>::value, "Should be POD."); // failed
データメンバに対するアクセス指定子が2種類以上¶
暗黙的なものを含めて、
static
ではないデータメンバに対するアクセス指定子が2種類以上ある構造体は POD ではありません。
struct MultipleAccessSpecifierTypes {
int public_variable;
private:
int private_variable;
};
static_assert(std::is_pod<MultipleAccessSpecifierTypes>::value, "Should be POD."); // failed
クラス¶
C++ における構造体とクラスの違いはデフォルトのアクセス指定子だけなので、 構造体と同じ条件でクラスも POD になります。
class FundamentalTypes {
public:
int16_t i;
double d;
};
static_assert(std::is_pod<FundamentalTypes>::value, "Should be POD.");