コンテンツにスキップ

C++/標準ライブラリ/メタプログラミングライブラリ

出典: フリー教科書『ウィキブックス(Wikibooks)』

この節では、C++ のメタプログラミング機能について説明します。これらの機能は、コンパイル時にプログラムを生成または修正することを可能にし、以下の表にまとめられています。

ヘッダー一覧[編集]

この章で扱うヘッダーファイルは以下の通りです。

整数シーケンス
<utility>
型特性
<type_traits>
有理数演算
<ratio>

整数シーケンス[編集]

コンパイル時整数シーケンスについて解説します。

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 だったり、テンプレート引数 ND の絶対値のいずれかが intmax_t 型で表現できない場合、プログラムは不正となります。

比の演算 (ratio.arithmetic)[編集]

  • ratio_add, ratio_subtract, ratio_multiply, ratio_divide というエイリアス テンプレートは、2つの比 R1R2 の算術演算の結果を表します。
  • 算術オーバーフローが発生しなければ 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 は定義されません。