このページはC++11に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
「エイリアステンプレート (alias templates)」は、テンプレートによって型の別名を定義する機能である。これによって、パラメータ化した型の別名付けができる。
エイリアステンプレートによる型の別名付けには、typedef
キーワードではなくusing
キーワードを使用する:
#include <vector>
// 型std::vectorに別名Vecを付ける。
// 要素型Tはパラメータ化する
template <class T>
using Vec = std::vector<T>;
int main()
{
// 要素型を渡してstd::vector型の別名を使用する
Vec<int> v;
v.push_back(3);
v.push_back(1);
v.push_back(4);
}
using
キーワードによる型の別名付けは、非テンプレートに対しても使用できる。この機能を「エイリアス宣言 (alias declaration)」という:
int f(int, int) { return 0; }
// int型にIntegerという別名を付ける
using Integer = int;
// int型を2つパラメータとしてとり、int型を返す関数ポインタに、
// FunctionPointerという名前を付ける
using FunctionPointer = int(*)(int, int);
// decltypeと組み合わせることで、
// 特定関数への関数ポインタの型をより簡単に取得できる
using FunctionPointerByDecltype = decltype(&f);
仕様
- テンプレートによる型の別名付けは、
using
キーワードによるもののみを許可し、typedef
キーワードに対しては許可しない -
エイリアステンプレートによって付けられた型の別名と元の型は等価と見なされ、それらの間でオーバーロードはできない
template <class T> using Vec = std::vector<T>; template <class T> void f(const Vec<T>&) {} template <class T> void f(const std::vector<T>&) {} // コンパイルエラー!再定義と見なされる
-
エイリアステンプレートに対しては、明示的な特殊化、および部分特殊化を許可しない
この機能が必要になった背景・経緯
エイリアステンプレートがなかったころは、パラメータ化した型の別名付けとして、クラステンプレートを使用していた:
template <class T>
struct Vec {
typedef std::vector<T> type;
};
Vec<int>::type v;
v.push_back(3);
このような回避策は標準ライブラリでも、std::allocator
クラスのrebind
で使用されている。T
型のメモリアロケータを使用している状況でほかの型をアロケートする必要ができた際には、U
型をアロケートするstd::allocator
型を取得する機能が必要とされる。そのような状況のために用意されているrebind
は、以下のように定義される:
template <class T>
struct allocator {
template <class U>
struct rebind { typedef allocator<U> other; };
};
typedef allocator<void> void_alloc;
// int型をアロケートするallocator型を取得
typedef void_alloc::rebind<int>::other int_alloc;
前述した例での::type
や、アロケータの例でのother
は冗長であり、必要とされることが多いこの機能には言語サポートが求められた。こういった経緯から、パラメータ化した型の別名付けが、言語機能としてサポートされることとなった。