最終更新日時:
が更新

履歴 編集

エイリアステンプレート(C++11)

概要

「エイリアステンプレート (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は冗長であり、必要とされることが多いこの機能には言語サポートが求められた。こういった経緯から、パラメータ化した型の別名付けが、言語機能としてサポートされることとなった。

参照