この節では、C++ のメタプログラミング機能について説明します。これらの機能は、コンパイル時にプログラムを生成または修正することを可能にし、以下の表にまとめられています。
ヘッダー一覧
編集この章で扱うヘッダーファイルは以下の通りです。
整数シーケンス
編集コンパイル時整数シーケンスについて解説します。
integer_sequenceクラステンプレート
編集- 整数シーケンスを表現するクラステンプレート
value_type
は整数型のTを要素として持つsize()
は要素数を返す
make_integer_sequenceエイリアステンプレート
編集integer_sequence
の別名を提供- N個の要素を持つ
integer_sequence
の特殊化を表す
integer_sequence
は、コンパイル時に決まる整数の列を表現するためのユーティリティです。テンプレート実引数演算を使って、コンパイル時にシーケンスを生成・操作できます。
例えば以下のようにして利用できます:
#include <cstddef> #include <iostream> #include <utility> template <std::size_t... Ints> void print_sequence(std::integer_sequence<std::size_t, Ints...> /*unused*/) { // パック展開を使ってシーケンス内の各要素を出力 ((std::cout << Ints << " "), ...); } auto main() -> int { print_sequence(std::make_integer_sequence<std::size_t, 5>()); // 0 1 2 3 4 return 0; }
この例では、make_integer_sequence
を使って0から4までの整数のシーケンスを生成し、print_sequence
に渡しています。print_sequence
の関数テンプレート引数演算でパック展開を行うことで、シーケンス内の各要素を出力できます。
このようにinteger_sequence
は、メタプログラミングにおける整数値の操作に役立ちます。標準ライブラリのアルゴリズムなどでも幅広く使われています。
型特性
編集ヘッダー <type_traits>
は C++11 で導入されたもので、プログラム内で使用される型の特性を検査し、操作するための仕組みを提供します。従来の型チェックとは異なり、type_traits
ヘッダーはコンパイル時に型に関する情報を取得し、テンプレートコードの汎用性向上、最適化、型関連のエラー検出、コンパイル時の型推論と変換などに役立ちます。
ヘッダーファイルの内容
編集- C++
#include <type_traits>
- このヘッダーファイルには、以下の主要な型特性テンプレートと型変換テンプレートが定義されています。
- 型分類特性テンプレート
-
is_integral
- 型が整数型かどうかを検査します。
is_floating_point
- 型が浮動小数点型かどうかを検査します。
is_array
- 型が配列型かどうかを検査します。
is_pointer
- 型がポインタ型かどうかを検査します。
is_void
- 型が
void
型かどうかを検査します。 is_null_pointer
- 型が
nullptr
型かどうかを検査します。 is_reference
- 型が参照型かどうかを検査します。
is_lvalue_reference
- 型が左辺値参照型かどうかを検査します。
is_rvalue_reference
- 型が右辺値参照型かどうかを検査します。
is_same
- 二つの型が同じかどうかを検査します。
is_convertible
- ある型が別の型に変換可能かどうかを検査します。
- 型特性検査テンプレート
-
is_const
- 型が const 修飾されているかどうかを検査します。
is_volatile
- 型が volatile 修飾されているかどうかを検査します。
is_unsigned
- 型が符号なし型かどうかを検査します。
is_signed
- 型が符号付き型かどうかを検査します.
is_fundamental
- 型が基底型かどうかを検査します。
is_compound
- 型が複合型かどうかを検査します。
is_abstract
- 型が抽象型かどうかを検査します.
is_polymorphic
- 型が多態型かどうかを検査します.
is_class
- 型がクラス型かどうかを検査します.
is_union
- 型がユニオン型かどうかを検査します.
is_enum
- 型が列挙型かどうかを検査します.
is_struct
- 型が構造体型かどうかを検査します.
- 型変換テンプレート
-
remove_const
- 型から const 修飾を取り除きます。
add_const
- 型に const 修飾を追加します。
remove_volatile
- 型から volatile 修飾を取り除きます。
add_volatile
- 型に volatile 修飾を追加します。
remove_cv
- 型から const と volatile 修飾を取り除きます。
add_cv
- 型に const と volatile 修飾を追加します。
remove_reference
- 型から参照修飾を取り除きます。
add_reference
- 型に参照修飾を追加します。
decay
- ポインタ型から指される型を取得します。
underlying_type
- 型の基底型を取得します。
make_signed
- 型を符号付き型に変換します。
make_unsigned
- 型を符号なし型に変換します.
aligned_storage
- 指定された配置要件を満たす型のストレージ型を取得します.
aligned_pointer
- 指定された配置要件を満たすポインタ型を取得します.
例
編集- C++
#include <type_traits> template <typename T> void is_integral_test() { static_assert(std::is_integral_v<T>, "T must be an integral type"); // ... } auto main() -> int { is_integral_test<int>(); // Ok is_integral_test<char>(); // Ok is_integral_test<float>(); // NG (float は整数型ではない) return 0; }
この例では、std::is_integral
テンプレートを使用して、T
型が整数型かどうかを検査しています。static_assert
マクロはコンパイル時に条件を検証し、条件が偽の場合はコンパイルエラーを出力します。
有理数演算
編集コンパイル時有理数計算 (ratio)
編集このセクションでは、C++ 標準ライブラリが提供するコンパイル時有理数計算 (ratio
) について説明します。
概要 (ratio.general)
編集ratio
ライブラリは、ratio
というクラステンプレートを提供します。- このテンプレートは、分子と分母がコンパイル時に定数として表現可能な
intmax_t
型の有限な有理数を正確に表します。 - コンパイル時有理数計算を通して、テンプレートパラメータ名は、型要件を表すために使用されます。
ヘッダーの概要 (ratio.syn)
編集- C++
// すべてフリーのネームスペース std において // 省略 (ratio クラステンプレート以降の宣言)
クラステンプレート ratio (ratio.ratio)
編集- C++
namespace std { template class ratio { public: static constexpr intmax_t num; // 分子 static constexpr intmax_t den; // 分母 using type = ratio; }; }
- テンプレート引数
D
が 0 だったり、テンプレート引数N
とD
の絶対値のいずれかがintmax_t
型で表現できない場合、プログラムは不正となります。
比の演算 (ratio.arithmetic)
編集ratio_add
,ratio_subtract
,ratio_multiply
,ratio_divide
というエイリアス テンプレートは、2つの比R1
とR2
の算術演算の結果を表します。- 算術オーバーフローが発生しなければ X と Y が計算されると、各エイリアスは U を
ratio::num
と等しく、V をratio::den
と等しくするような比を表します。 - U または V を
intmax_t
で表現できない場合、プログラムは不正となります。
比の比較 (ratio.comparison)
編集ratio_equal
,ratio_not_equal
,ratio_less
,ratio_less_equal
,ratio_greater
,ratio_greater_equal
というテンプレート構造体は、2 つの比の関係を表します。
SI 接頭辞 (ratio.si)
編集C++ 標準ライブラリは、以下の SI 接頭辞に対応する typedef を定義しています。
- yocto
- zepto
- zetta
- yotta
ただし、定数が intmax_t
型で表現できない場合は、typedef は定義されません。