名稱空間
變體
操作

類型別名、別名模板 (C++11 起)

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
通用主題
流程控制
條件執行語句
if
迭代語句(迴圈)
for
range-for (C++11)
跳轉語句
函式
函式宣告
Lambda 函式表示式
inline 說明符
動態異常規範 (直到 C++17*)
noexcept 說明符 (C++11)
異常
名稱空間
型別
說明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期說明符
初始化
表示式
替代表示
字面量
布林型 - 整型 - 浮點型
字元型 - 字串型 - nullptr (C++11)
使用者定義 (C++11)
工具
屬性 (C++11)
型別
typedef 宣告
類型別名宣告 (C++11)
型別轉換
記憶體分配
類特有的函式屬性
explicit (C++11)
static

特殊成員函式
模板
雜項
 
 

類型別名是引用先前定義的型別的名稱(類似於 typedef)。

別名模板是引用一族型別的名稱。

目錄

[編輯] 語法

別名宣告是具有以下語法的宣告

using identifier attr (可選) = type-id ; (1)
template < template-parameter-list >

using identifier attr (可選) = type-id ;

(2)
template < template-parameter-list > requires constraint

using identifier attr (可選) = type-id ;

(3) (C++20 起)
屬性 - 任意數量的屬性的可選序列
識別符號 - 此宣告引入的名稱,它成為型別名稱 (1) 或模板名稱 (2)
模板引數列表 - 模板引數列表,如模板宣告中所示
約束 - 一個約束表示式,它限制了此別名模板接受的模板引數
型別標識 - 抽象宣告符或任何其他有效的 type-id(可能引入新型別,如type-id中指出)。type-id 不能直接或間接引用 identifier。請注意,識別符號的宣告點位於 type-id 之後的Semicolon。

[編輯] 解釋

1) 類型別名宣告引入了一個名稱,該名稱可以用作 type-id 所表示型別的同義詞。它不引入新型別,也不能改變現有型別名稱的含義。類型別名宣告和 typedef 宣告之間沒有區別。此宣告可以出現在塊作用域、類作用域或名稱空間作用域中。
2) 別名模板是一個模板,當其特化時,它等效於將別名模板的模板引數替換為 type-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>>

當特化別名模板的結果是依賴template-id時,後續替換適用於該template-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

在推導模板模板引數時,模板引數推導從不推導別名模板。

不可能部分顯式特化別名模板。

與任何模板宣告一樣,別名模板只能在類作用域或名稱空間作用域中宣告。

別名模板宣告中出現的lambda 表示式的型別在模板例項化之間是不同的,即使 lambda 表示式不依賴也是如此。

template<class T>
using A = decltype([] {}); // A<int> and A<char> refer to different closure types
(C++20 起)

[編輯] 注意

功能測試宏 標準 特性
__cpp_alias_templates 200704L (C++11) 別名模板

[編輯] 關鍵詞

using

[編輯] 示例

#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++ 標準。

缺陷報告 應用於 釋出時的行為 正確的行為
CWG 1558 C++11 別名特化中未使用的引數
是否參與替換未指定
替換
已執行

[編輯] 另請參閱

typedef 宣告 為型別建立同義詞[編輯]
命名空間別名 建立現有名稱空間的別名[編輯]