型エイリアス、エイリアステンプレート (C++11以降)
From cppreference.com
型エイリアスは、以前に定義された型を参照する名前です (typedef と同様)。
エイリアステンプレートは、型のファミリを参照する名前です。
目次 |
[編集] 構文
エイリアス宣言は、以下の構文を持つ宣言です。
using identifier attr (省略可能) = type-id ; |
(1) | ||||||||
template < template-parameter-list >
|
(2) | ||||||||
template < template-parameter-list > requires constraint
|
(3) | (C++20以降) | |||||||
| attr | - | 任意の数の属性のオプションのシーケンス |
| identifier | - | この宣言によって導入される名前。型名 (1) またはテンプレート名 (2) となる |
| template-parameter-list | - | テンプレート宣言と同様のテンプレートパラメータリスト |
| constraint (制約) | - | このエイリアステンプレートが受け入れるテンプレートパラメータを制限する制約式 |
| type-id | - | 抽象宣言子、またはその他の有効な型ID (型IDで述べられているように、新しい型を導入する可能性がある)。型IDは、直接的または間接的に識別子を参照することはできない。識別子の宣言点は、型IDに続くセミコロンであることに注意。 |
[編集] 解説
1) 型エイリアス宣言は、型IDによって示される型の同義語として使用できる名前を導入する。新しい型を導入するものではなく、既存の型名の意味を変更することはできない。型エイリアス宣言とtypedef宣言の間に違いはない。この宣言は、ブロックスコープ、クラススコープ、または名前空間スコープに現れることができる。
2) エイリアステンプレートは、特殊化されたときに、エイリアステンプレートのテンプレート引数を型IDのテンプレートパラメータに置換した結果と等価になるテンプレートである。
template<class T> struct Alloc {}; template<class T> using Vec = vector<T, Alloc<T>>; // type-id is vector<T, Alloc<T>> Vec<int> v; // Vec<int> is the same as vector<int, Alloc<int>>
エイリアステンプレートを特殊化した結果が依存するテンプレートIDである場合、後続の置換はそのテンプレートIDに適用される。
template<typename...> using void_t = void; template<typename T> void_t<typename T::foo> f(); f<int>(); // error, int does not have a nested type foo
エイリアステンプレートを特殊化したときに生成される型は、直接的または間接的に自身の型を使用することは許されない。
template<class T> struct A; template<class T> using B = typename A<T>::U; // type-id is A<T>::U template<class T> struct A { typedef B<T> U; }; B<short> b; // error: B<short> uses its own type via A<short>::U
エイリアステンプレートは、テンプレートテンプレートパラメータを推論する際のテンプレート引数推論によっては推論されない。
エイリアステンプレートを部分特殊化したり、明示的に特殊化することはできない。他のテンプレート宣言と同様に、エイリアステンプレートはクラススコープまたは名前空間スコープでのみ宣言できる。
|
エイリアステンプレート宣言に現れるラムダ式の型は、ラムダ式が依存しない場合でも、そのテンプレートのインスタンス化ごとに異なる。 template<class T> using A = decltype([] {}); // A<int> and A<char> refer to different closure types |
(C++20以降) |
[編集] 注釈
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_alias_templates |
200704L |
(C++11) | エイリアステンプレート |
[編集] キーワード
[編集] 例
このコードを実行
#include <iostream> #include <string> #include <type_traits> #include <typeinfo> // type alias, identical to // typedef std::ios_base::fmtflags flags; using flags = std::ios_base::fmtflags; // the name 'flags' now denotes a type: flags fl = std::ios_base::dec; // type alias, identical to // typedef void (*func)(int, int); using func = void (*) (int, int); // the name 'func' now denotes a pointer to function: void example(int, int) {} func f = example; // alias template template<class T> using ptr = T*; // the name 'ptr<T>' is now an alias for pointer to T ptr<int> x; // type alias used to hide a template parameter template<class CharT> using mystring = std::basic_string<CharT, std::char_traits<CharT>>; mystring<char> str; // type alias can introduce a member typedef name template<typename T> struct Container { using value_type = T; }; // which can be used in generic programming template<typename ContainerT> void info(const ContainerT& c) { typename ContainerT::value_type T; std::cout << "ContainerT is `" << typeid(decltype(c)).name() << "`\n" "value_type is `" << typeid(T).name() << "`\n"; } // type alias used to simplify the syntax of 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) { return 1; } struct S { virtual ~S() {} }; int main() { Container<int> c; info(c); // Container::value_type will be int in this function // fpoly_only(c); // error: enable_if prohibits this S s; fpoly_only(s); // okay: enable_if allows this }
実行結果の例
ContainerT is `struct Container<int>` value_type is `int`
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 1558 | C++11 | エイリアス特殊化における未使用引数が 置換に参加するかどうかが指定されていなかった |
置換 が実行される |
[編集] 関連項目
typedef宣言
|
型の同義語を作成する |
| 名前空間エイリアス | 既存の名前空間のエイリアスを作成する |