最終更新: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 を使うこともできます:
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>
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値にアクセスする必要がなくなり、コードはより簡潔で直感的になります。
変数テンプレートの利点¶
- 冗長なコードの削減:変数テンプレートにより、型に基づく変数を直接定義でき、
structやstd::integral_constantでbool値をカプセル化する冗長なコードを避けられます。 - 可読性の向上:変数テンプレートは構文を簡潔にし、特に大量の型特性を書くときにコードをより明快にします。
- テンプレートの特殊化のサポート:型エイリアステンプレートとは異なり、変数テンプレートは完全特殊化でも部分特殊化でも特殊化できます。特定の型専用のロジックを定義でき、拡張性の問題を心配する必要がありません。
C++17 のさらなる改善¶
C++17 は変数テンプレートの適用範囲をさらに広げ、すべての型特性に変数テンプレートのヘルパーを提供しました。例えば、std::is_same には std::is_same_v という変数テンプレートが導入され、型特性の値へのアクセスが簡潔になります:
この方法により、型特性の使用はより簡潔になり、開発者は毎回 ::value にアクセスすることなく、変数テンプレートを直接利用できます。
実際の例¶
この機能は実際の領域でもよく使われています。例えば、データベースで異なるサイズのメモリブロックを割り当てるとき、テンプレートによって異なる型のブロックサイズを初期化できます。
template <typename T>
constexpr size_t block_size = 1024; // 默认大小
template <>
constexpr size_t block_size<double> = 2048; // double 类型需要更多内存
関連トピック¶
- C++17 [[nodiscard]] 属性 | C++那些事
- C++17 std::string_view | C++那些事
- C++17 PMR メモリリソース | C++那些事
- C++17 17の高度な機能 | C++那些事
- C++17 クラステンプレートのテンプレート引数推論 CTAD | C++那些事
- C++17 optional_ref | C++那些事
- C++17 std::variant | C++那些事
- C++17 構造化束縛 | C++那些事
- C++17 テンプレート auto 推論 | C++那些事