コンテンツにスキップ

最終更新:2026-10-12

C++17 変数テンプレート

C++那些事の変数テンプレート

テンプレートコードを書くとき、私たちはさまざまな型特性(type traits)を定義して使うことがよくあります。これらの型特性は通常、コンパイル時に型を判定するために使われ、STLが提供する std::is_const、std::is_same、std::is_reference などがその例です。これらの特性を通じて、開発者は型の属性に基づいてコンパイル時の意思決定ができます。

本記事では、C++14 変数テンプレート(variable templates) を使って型特性の記述を簡潔にする方法を紹介し、簡単な例を示します。

C++11

C++11 では、型特性を書くには通常 struct や std::integral_constant を使ってbool値をカプセル化する必要がありました。例えば、型が float かどうかを判定する型特性 is_float を書くには、次のように実装できます:

template <typename T>
struct is_float {
    static constexpr bool value = std::is_same<T, float>::value;
};

あるいはもう少し簡潔に、型エイリアスと std::integral_constant を使うこともできます:

template <typename T>
using is_float = std::integral_constant<bool, std::is_same<T, float>::value>;

struct を直接使うよりは簡潔ですが、結局のところ定義しているのは型であり、bool値を直接得ているわけではありません。この特性を使うときは、::value メンバを通じてbool値を取得する必要があります:

template <typename T>
void test(T t){
    if (is_float<T>::value){
        std::cout << "I'm a float" << std::endl;
    } else {
        std::cout << "I'm not a float" << std::endl;
    }
}

これでも動作しますが、なお2つの点で不十分です: 1. 型特性を使うたびに ::value にアクセスしなければなりません。 2. 新しい型特性を定義するとき、新しい型や型エイリアスを宣言しなければならず、コードの冗長さが増します。

C++14 変数テンプレートの導入

C++14 では 変数テンプレート が導入され、型に依存する変数を直接定義できるようになりました。この機能は型特性の記述を簡潔にし、bool値をカプセル化するために型エイリアスや struct を使う必要がなく、直接bool値を定義できるようになります。

書き直した is_float 特性は次のとおりです:

template <typename T>
constexpr bool is_float = std::is_same<T, float>::value;

この方法はより簡潔で明快であり、不要なコードが除かれています。使い方もより簡単です:

template <typename T>
void test(T t){
    if (is_float<T>){
        std::cout << "I'm a float" << std::endl;
    } else {
        std::cout << "I'm not a float" << std::endl;
    }
}

以前の書き方と比べると、変数テンプレートを使えば、::value を通じてbool値にアクセスする必要がなくなり、コードはより簡潔で直感的になります。

変数テンプレートの利点

  1. 冗長なコードの削減:変数テンプレートにより、型に基づく変数を直接定義でき、struct や std::integral_constant でbool値をカプセル化する冗長なコードを避けられます。
  2. 可読性の向上:変数テンプレートは構文を簡潔にし、特に大量の型特性を書くときにコードをより明快にします。
  3. テンプレートの特殊化のサポート:型エイリアステンプレートとは異なり、変数テンプレートは完全特殊化でも部分特殊化でも特殊化できます。特定の型専用のロジックを定義でき、拡張性の問題を心配する必要がありません。

C++17 のさらなる改善

C++17 は変数テンプレートの適用範囲をさらに広げ、すべての型特性に変数テンプレートのヘルパーを提供しました。例えば、std::is_same には std::is_same_v という変数テンプレートが導入され、型特性の値へのアクセスが簡潔になります:

template <typename T>
constexpr bool is_float = std::is_same_v<T, float>;

この方法により、型特性の使用はより簡潔になり、開発者は毎回 ::value にアクセスすることなく、変数テンプレートを直接利用できます。

実際の例

この機能は実際の領域でもよく使われています。例えば、データベースで異なるサイズのメモリブロックを割り当てるとき、テンプレートによって異なる型のブロックサイズを初期化できます。

template <typename T>
constexpr size_t block_size = 1024;  // 默认大小

template <>
constexpr size_t block_size<double> = 2048;  // double 类型需要更多内存

関連トピック

コメント