型エイリアス、エイリアステンプレート (C++11以上)
提供: cppreference.com
型エイリアスは以前に定義された型を参照する名前です (typedef と同様です)。
エイリアステンプレートは型のファミリーを参照する名前です。
目次 |
[編集]構文
エイリアス宣言は以下の構文を持つ宣言です。
using identifierattr(オプション)= type-id; | (1) | ||||||||
template < template-parameter-list>
| (2) | ||||||||
attr | - | オプショナルな任意個の属性の並び。 |
identifier | - | この宣言によって導入される名前。 型名 (1) またはテンプレート名 (2) のいずれかになります。 |
template-parameter-list | - | テンプレート引数リスト。 テンプレート宣言の場合と同様です。 |
type-id | - | 抽象宣言子または何らかの他の有効な type-id (type-id で述べられているように、新しい型を導入する場合があります)。 type-id が直接または間接的に identifier を参照することはできません。 identifier の宣言地点は type-id の後のセミコロンです。 |
[編集]説明
1) 型エイリアス宣言は type-id によって表される型に対する同義語として使用できる名前を導入します。 新しい型は導入せず、既存の型名の意味を変更することはできません。 型エイリアス宣言と typedef 宣言の間に違いはありません。 この宣言はブロックスコープ、クラススコープ、または名前空間スコープに現れることができます。
2) エイリアステンプレートは、特殊化されたときに type-id 内のテンプレート仮引数をエイリアステンプレートのテンプレート実引数で置き換えた結果と同等となる、テンプレートです。
template<class T>struct Alloc {};template<class T>using Vec = vector<T, Alloc<T>>;// type-id は vector<T, Alloc<T>> です。 Vec<int> v;// Vec<int> は vector<int, Alloc<int>> と同じです。
エイリアステンプレートの特殊化の結果が依存 template-id であるとき、その後の置き換えはその template-id に適用されます。 template<typename...>using void_t =void;template<typename T> void_t<typename T::foo> f(); f<int>();// エラー、 int はネストした型 foo を持ちません。 | (C++14以上) |
エイリアステンプレートを特殊化するときに生成される型は、直接または間接的な自身の型の使用を許容しません。
template<class T>struct A;template<class T>using B =typename A<T>::U;// type-id は A<T>::U です。template<class T>struct A {typedef B<T> U;}; B<short> b;// エラー、 B<short> は A<short>::U を介して自身の型を使用しています。
テンプレートテンプレート引数を推定するとき、エイリアステンプレートがテンプレートの実引数推定によって推定されることはありません。
エイリアステンプレートを部分特殊化または明示的特殊化することはできません。あらゆるテンプレート宣言と同様に、エイリアステンプレートはクラススコープまたは名前空間スコープでのみ宣言できます。
エイリアステンプレート宣言内に現れるラムダ式の型は、たとえそのラムダ式が依存でないときでも、そのテンプレートの実体化間で異なります。 template<class T>using A = decltype([]{});// A<int> と A<char> は異なるクロージャ型を参照します。 | (C++20以上) |
[編集]例
Run this code
#include <string>#include <ios>#include <type_traits> // 型エイリアス。 typedef std::ios_base::fmtflags flags; と同じです。using flags =std::ios_base::fmtflags;// 以後、名前「flags」は型を表します。 flags fl =std::ios_base::dec; // 型エイリアス。 typedef void (*func)(int, int); と同じです。using func =void(*)(int, int);// 以後、名前「func」は関数へのポインタを表します。void example(int, int){} func f = example; // エイリアステンプレート。template<class T>using ptr = T*;// 以後、名前「ptr<T>」は T へのポインタの別名です。 ptr<int> x; // テンプレート引数を隠すために使用される型エイリアス。template<class CharT>using mystring =std::basic_string<CharT, std::char_traits<CharT>>; mystring<char> str; // 型エイリアスはメンバ typedef 名を導入できます。template<typename T>struct Container {using value_type = T;};// これは総称プログラミングで使用できます。template<typename ContainerType>void g(const ContainerType& c){typename ContainerType::value_type n;} // std::enable_if の構文を単純化するために使用される型エイリアス。template<typename T>using Invoke =typename T::type;template<typename Condition>using EnableIf = Invoke<std::enable_if<Condition::value>>;template<typename T, typename= EnableIf<std::is_polymorphic<T>>>int fpoly_only(T t){return1;} struct S {virtual ~S(){}}; int main(){ Container<int> c; g(c);// この関数内では Container::value_type は int です。// fpoly_only(c); // エラー、 enable_if はこれを禁止します。 S s; fpoly_only(s);// OK、 enable_if はこれを許容します。}
[編集]欠陥報告
以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。
DR | 適用先 | 発行時の動作 | 正しい動作 |
---|---|---|---|
CWG 1558 | C++14 | whether unused arguments in an alias specialization participate in substitition is not specified | substitution is performed |
[編集]関連項目
typedef 宣言 | 型の同義語を作成します |