C++のis_emptyテンプレートとは?空クラス判定の基本と実例を徹底解説
本記事では、C++ STLに用意されているstd::is_emptyテンプレートの仕組み、構文、そして具体的な使用例について詳しく解説します。
is_emptyは、<type_traits>ヘッダーに定義されているクラステンプレートで、指定した型Tが「空クラス(empty class)」であるかどうかをコンパイル時に判定するために使用します。
空クラスとは何か?
クラスの中に実質的なデータが格納されていない場合、そのクラスは「空」とみなされます。空クラスと判定されるためには、以下の条件をすべて満たす必要があります。
- 長さ0のビットフィールド以外に、非静的データメンバーを持たないこと
- 仮想基底クラスや仮想関数を持たないこと
- 空でない基底クラスを持たないこと
なお、静的メンバーやメンバー関数、デストラクターなどはオブジェクトごとのデータサイズに影響しないため、これらが存在してもクラスは空と判定されます。
構文
template <class T> is_empty;
パラメータ
このテンプレートは、判定対象となる型Tを1つのパラメータとして受け取り、その型が空クラスであるかどうかをチェックします。
戻り値
ブール値(bool)を返します。指定された型が空クラスであればtrue、そうでなければfalseとなります。
基本的な使い方
入力: class A{};
is_empty<A>::value;
出力: true
入力: class B { void fun() {} };
is_empty<B>::value;
出力: true
クラスBにはメンバー関数fun()が定義されていますが、メンバー関数はオブジェクトのサイズに影響しないため、Bも空クラスとして判定されます。
サンプルコード1:クラスの場合
#include <iostream>
#include <type_traits>
using namespace std;
class TP_1 {
};
class TP_2 {
int var;
};
class TP_3 {
static int var;
};
class TP_4 {
~TP_4();
};
int main() {
cout << boolalpha;
cout << "変数を持たないクラスの判定結果: " << is_empty<TP_1>::value;
cout << "\n非静的メンバー変数を1つ持つクラスの判定結果: " << is_empty<TP_2>::value;
cout << "\n静的メンバー変数を1つ持つクラスの判定結果: " << is_empty<TP_3>::value;
cout << "\nデストラクターを持つクラスの判定結果: " << is_empty<TP_4>::value;
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
変数を持たないクラスの判定結果: true 非静的メンバー変数を1つ持つクラスの判定結果: false 静的メンバー変数を1つ持つクラスの判定結果: true デストラクターを持つクラスの判定結果: true
結果の解説
- TP_1:メンバーを一切持たないため、空クラスと判定されます(true)。
- TP_2:非静的メンバー変数int varを持つため、空クラスではありません(false)。
- TP_3:静的メンバー変数は個々のオブジェクトに属さず、クラス全体で1つだけ存在するため、空クラスと判定されます(true)。
- TP_4:デストラクターの宣言はオブジェクトのデータ領域に影響しないため、空クラスと判定されます(true)。
サンプルコード2:構造体の場合
is_emptyは、struct(構造体)に対してもまったく同じように機能します。
#include <iostream>
#include <type_traits>
using namespace std;
struct TP_1 {
};
struct TP_2 {
int var;
};
struct TP_3 {
static int var;
};
struct TP_4 {
~TP_4();
};
int main() {
cout << boolalpha;
cout << "変数を持たない構造体の判定結果: " << is_empty<TP_1>::value;
cout << "\n非静的メンバー変数を1つ持つ構造体の判定結果: " << is_empty<TP_2>::value;
cout << "\n静的メンバー変数を1つ持つ構造体の判定結果: " << is_empty<TP_3>::value;
cout << "\nデストラクターを持つ構造体の判定結果: " << is_empty<TP_4>::value;
return 0;
}
実行結果
上記のコードを実行すると、次の出力が得られます。
変数を持たない構造体の判定結果: true 非静的メンバー変数を1つ持つ構造体の判定結果: false 静的メンバー変数を1つ持つ構造体の判定結果: true デストラクターを持つ構造体の判定結果: true
まとめ
std::is_emptyは、型が空クラスかどうかをコンパイル時に判定できる便利なタイプトライトです。特に、空クラスを基底クラスとして継承してもオブジェクトサイズが増加しない「EBO(Empty Base Optimization:空基底クラス最適化)」といった最適化技法を実装する際に活用されます。テンプレートメタプログラミングにおいて、型の特性に応じて処理を分岐させたい場合にも非常に役立つツールと言えるでしょう。
-
C++における構造体とクラスの違いとは?アクセス指定子の挙動を実例付きで解説
はじめにC++において、構造体(struct)とクラス(class)は本質的にはほぼ同じものです。どちらもメンバ変数やメンバ関数を持つことができ、継承・カプセル化といったオブジェクト指向の機能も同様に利用できます。しかし、両者にはいくつかの細かな違いが存在します。この記事では、その違いをサンプルコードと実行結果を交えてわかりやすく解説します。違い1:メンバのデフォルトのアクセスレベル最も大きな違いは、メンバのデフォルトのアクセス権限です。クラスのメンバはデフォルトで「private(非公開)」になりますが、構造体のメンバはデフォルトで「public(公開)」になります。実際に、以下の2つのコー
-
C++のローカルクラスとは?特徴・制約と実装例をわかりやすく解説
ローカルクラスとは C++において、関数の中で宣言されたクラスは「ローカルクラス」と呼ばれます。これは、そのクラスが定義された関数の内部でのみ有効であるためです。 まず、ローカルクラスの基本的な構造を見てみましょう。 #include<iostream> using namespace std; void func() { class LocalClass { }; } int main() { return 0; } 上記の例では、関数 func() の中で LocalClass が定義されています。このように関数の内部で宣言されたクラスが、ローカルクラス