反射擴充套件
C++ 反射擴充套件,ISO/IEC TS 23619:2021,指定了對核心語言的修改,並定義了本頁列出的 C++ 標準庫新元件。
反射 TS 基於 C++20 標準(但概念的定義是按照概念 TS的風格指定的)。
[編輯] 核心語言變更
[編輯] reflexpr-說明符
一個 reflexpr-說明符 的形式為 reflexpr
(
reflexpr-運算元 )
,並指定一個元物件型別(見下文)。
reflexpr-運算元 可以是以下之一:
::
|
(1) | ||||||||
型別標識 | (2) | ||||||||
巢狀名說明符(可選) 名稱空間名 | (3) | ||||||||
id-表示式 | (4) | ||||||||
( 表示式 ) |
(5) | ||||||||
函式呼叫表示式 | (6) | ||||||||
函式式型別轉換表示式 | (7) | ||||||||
其中 函式呼叫表示式 為
字尾表示式 ( 表示式列表(可選) ) |
|||||||||
而 函式式型別轉換表示式 是以下執行顯式轉換的表示式型別
簡單型別說明符 ( 表示式列表(可選) ) |
(1) | ||||||||
typename-說明符 ( 表示式列表(可選) ) |
(2) | ||||||||
簡單型別說明符 大括號初始化列表 | (3) | ||||||||
typename-說明符 大括號初始化列表 | (4) | ||||||||
reflexpr-說明符 的運算元應為型別、名稱空間、列舉器、變數、資料成員、函式引數、捕獲實體、函式呼叫表示式 或 函式式型別轉換表示式,以及帶括號的表示式。reflexpr(::) 反射全域性名稱空間。
對於形式為 (
表示式 )
的 reflexpr-運算元,該 表示式 應為(可能多層括號的)函式呼叫表示式 或 函式式型別轉換表示式。
如果一個無括號運算元可以被視為 型別標識 或 函式式型別轉換表示式,則它被視為 型別標識。括號可用於區分函式式型別轉換和 型別標識。例如,給定一個具有預設建構函式的類型別 X
,reflexpr(X()) 反射函式型別 X(),而 reflexpr((X())) 反射表示式 X()。
如果運算元同時指定一個別名和一個類名,則由 reflexpr-說明符表示的型別將反射該別名並滿足 `reflect::Alias`。
如果運算元指定一個在塊作用域中宣告的名稱,並且該命名實體既未被捕獲也不是函式引數,則程式格式錯誤。
[編輯] 元物件型別
元物件型別是一種未命名、不完整的名稱空間作用域類型別。當且僅當一個型別是元物件型別時,它才滿足 `reflect::Object` 概念。元物件型別可能滿足其他概念,具體取決於 `reflexpr` 的運算元。
反覆將 `reflexpr` 應用於同一運算元是否產生相同或不同的型別是未指定的。如果元物件型別反映一個不完整的類型別,則某些型別轉換無法應用。
元物件型別允許透過型別特徵或型別轉換檢查 `reflexpr` 運算元的一些屬性。
[編輯] 過載決議
如果 函式呼叫表示式 的 字尾表示式 是類型別,即 e 在 函式呼叫表示式 e(args) 中是類型別,則不應使用 字尾表示式 (e) 型別的使用者定義轉換函式。
如果 字尾表示式 不是類型別,它應命名一個函式,該函式是過載決議的唯一結果。
struct Functor { void operator()(int) const; using fptr_t = void(*)(std::nullptr_t); operator fptr_t() const; }; using Meta0 = reflexpr(Functor{}(0)); // OK // using Meta1 = reflexpr(Functor{}(nullptr)); // error: conversion function used
[編輯]
別名是透過 typedef 宣告、別名宣告或 using 宣告引入的名稱。
實體或別名 B
與實體或別名 A
反射相關,如果
-
A
和B
是相同的實體或別名, -
A
是變數或列舉器,且B
是A
的型別, -
A
是列舉,且B
是A
的基礎型別, -
A
是類,且B
是A
的成員或基類, -
A
是指定實體B
的非模板別名, -
A
不是全域性名稱空間,且B
是A
的封閉類或名稱空間, -
A
是帶括號的表示式 (B
), -
A
是閉包型別B
的 lambda 捕獲, -
A
是 lambda 捕獲B
的閉包型別, -
B
是由 函式式型別轉換表示式A
指定的型別, -
B
是透過過載決議為 函式呼叫表示式A
選擇的函式, -
B
是函式A
的返回型別、引數型別或函式型別,或者 -
B
與實體或別名X
反射相關,且X
與A
反射相關。
反射關係是自反和傳遞的,但不是對稱的。
非正式地說,B
與 A
反射相關的情況意味著 B
參與了 A
的宣告或定義。
對由 reflexpr-說明符 表示的型別進行零次或多次連續的型別轉換(產生元物件型別),可以檢查與運算元反射相關的實體和別名;這樣的元物件型別被認為反映了相應的反射相關實體或別名。
struct X; struct B { using X = ::X; typedef X Y; }; struct D : B { using B::Y; }; // ::X, but not B::X or B::Y is reflection-related to D::Y
[編輯] 雜項
- 用作 reflexpr-運算元 的表示式是未求值表示式,並且可能在編譯時求值。
- 為了確定透過捕獲預設值在 lambda 表示式中捕獲的變數,`reflexpr` 運算元不被視為未求值運算元。
- 由元物件型別 `T` 反射的具有靜態儲存期的函式或變數,透過特化 std::experimental::reflect::get_pointer<T> 進行odr-use,如同透過獲取提名該函式或變數的 id-expression 的地址一樣。
- 可以有多個元物件型別的定義,只要所有對該型別的操作都產生相同的常量表達式結果。
- 如果一個型別是由 reflexpr-說明符表示的,並且其運算元,則該型別是依賴的:
[編輯] 關鍵字
[編輯] 預定義特性測試宏
__cpp_reflection (反射 TS) |
值至少為 201902 表示支援反射 TS (宏常量) |
[編輯] 庫支援
[編輯] 概念
定義於標頭檔案
<experimental/reflect> | |
定義於名稱空間
std::experimental::reflect | |
定義於內聯名稱空間
std::experimental::reflect::v1 | |
(反射 TS) |
指定一個型別是元物件型別 (概念) |
(反射 TS) |
指定一個元物件型別是元物件序列型別 (概念) |
(反射 TS) |
指定元物件型別反映一個模板引數作用域 (概念) |
(反射 TS) |
指定一個元物件型別反映一個具有關聯(可能為空)名稱的實體或別名 (概念) |
(反射 TS) |
指定元物件型別反映類型別名、命名空間別名或透過 using-宣告引入的別名 (概念) |
(反射 TS) |
指定元物件型別反映類的一個 成員宣告 (概念) |
(反射 TS) |
指定元物件型別反映列舉器 (概念) |
(反射 TS) |
指定元物件型別反映變數或資料成員 (概念) |
(反射 TS) |
指定一個元物件型別滿足 `RecordMember`、`Enumerator` 或 `Variable`,或者反映全域性名稱空間以外的名稱空間 (概念) |
(反射 TS) |
指定元物件型別反映一個具有型別的實體 (概念) |
(反射 TS) |
指定一個元物件型別反映一個名稱空間 (概念) |
(反射 TS) |
指定一個元物件型別反映全域性名稱空間 (概念) |
(反射 TS) |
指定元物件型別反映非聯合類型別 (概念) |
(反射 TS) |
指定元物件型別反映列舉型別 (概念) |
(反射 TS) |
指定元物件型別反映類型別 (概念) |
(反射 TS) |
指定一個元物件型別反映一個名稱空間、類、列舉、函式、閉包型別、模板引數作用域 (概念) |
(反射 TS) |
指定一個元物件型別反映一個型別 (概念) |
(反射 TS) |
指定一個元物件型別反映一個列舉器或一個 constexpr 變數 (概念) |
(反射 TS) |
指定元物件型別反映從 `get_base_classes` 獲取的直接基類 (概念) |
(反射 TS) |
指定一個元物件型別反映一個函式引數 (概念) |
(反射 TS) |
指定元物件型別反映一個函式(包括建構函式和解構函式) (概念) |
(反射 TS) |
指定一個元物件型別反映一個表示式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個帶括號的表示式 (概念) |
(反射 TS) |
指定元物件型別反映一個 函式呼叫表示式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個 函式式型別轉換表示式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個函式(不包括建構函式和解構函式) (概念) |
(反射 TS) |
指定元物件型別反映一個成員函式(不包括建構函式和解構函式) (概念) |
(反射 TS) |
指定一個元物件型別反映一個特殊成員函式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個建構函式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個解構函式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個運算子函式或一個轉換函式 (概念) |
(反射 TS) |
指定一個元物件型別反映一個轉換函式 (概念) |
(反射 TS) |
指定元物件型別反映非泛型 lambda 的閉包型別 (概念) |
(反射 TS) |
指定一個元物件型別反映一個 lambda 捕獲 (概念) |
[編輯] 元物件操作
定義於標頭檔案
<experimental/reflect> | |
定義於名稱空間
std::experimental::reflect | |
定義於內聯名稱空間
std::experimental::reflect::v1 | |
| |
(反射 TS) |
檢查兩個元物件型別是否反映相同的實體或別名 (類模板) |
(反射 TS) |
獲取被反射實體或別名宣告的推定行號 (類模板) |
(反射 TS) |
獲取被反射實體或別名宣告的實現定義的列號 (類模板) |
(反射 TS) |
獲取被反射實體或別名宣告的推定檔名 (類模板) |
| |
(反射 TS) |
獲取元物件序列的大小 (類模板) |
(反射 TS) |
獲取序列中指定索引的元物件型別 (類模板) |
(反射 TS) |
將模板應用於元物件序列 (類模板) |
| |
(反射 TS) |
檢查被反射實體或別名是否未命名 (類模板) |
(反射 TS) |
獲取被反射實體或別名的非限定名稱 (類模板) |
(反射 TS) |
獲取被反射實體或別名的實現定義的顯示名稱 (類模板) |
| |
(反射 TS) |
獲取反映被反射別名的關聯實體的元物件型別 (類模板) |
| |
(反射 TS) |
獲取反映被反射實體或別名型別的元物件型別 (類模板) |
(反射 TS) |
獲取被反射實體或別名的型別 (類模板) |
(反射 TS) |
檢查元物件型別是否反映列舉型別 (類模板) |
(反射 TS) |
檢查元物件型別是否反映聯合型別 (類模板) |
檢查元物件型別是否反映使用 class 或 struct 分別宣告的非聯合類型別 (類模板) | |
| |
(反射 TS) |
獲取反映被反射實體或別名作用域的元物件型別 (類模板) |
| |
(反射 TS) |
獲取反映給定基類關係中基類的元物件型別 (類模板) |
| |
(反射 TS) |
檢查被反射成員或基類是否為公共的 (類模板) |
(反射 TS) |
檢查被反射成員或基類是否受保護 (類模板) |
(反射 TS) |
檢查被反射成員或基類是否為私有的 (類模板) |
| |
獲取一個元物件序列型別,其元素反映被反射類的公共、可訪問或所有資料成員 (類模板) | |
獲取一個元物件序列型別,其元素反映被反射類的公共、可訪問或所有成員函式 (類模板) | |
(反射 TS) |
獲取一個元物件序列型別,其元素反映被反射類的所有建構函式 (類模板) |
(反射 TS) |
獲取一個元物件序列型別,其元素反映在被反射類中宣告的所有運算子函式和轉換函式 (類模板) |
(反射 TS) |
獲取反映被反射類解構函式的元物件型別 (類模板) |
獲取一個元物件序列型別,其元素反映被反射類的公共、可訪問或所有巢狀型別或成員 typedef (類模板) | |
獲取一個元物件序列型別,其元素反映被反射類的公共、可訪問或所有基類 (類模板) | |
| |
(反射 TS) |
檢查被反射列舉是否為作用域列舉 (類模板) |
(反射 TS) |
獲取一個元物件序列型別,其元素反映被反射列舉的列舉器 (類模板) |
(反射 TS) |
獲取反映被反射列舉基礎型別的元物件型別 (類模板) |
| |
(反射 TS) |
獲取被反射變數的值,該值是一個常量表達式 (類模板) |
(反射 TS) |
檢查變數是否使用 thread_local 宣告 (類模板) |
| |
(反射 TS) |
檢查被反射引數是否具有預設引數 (類模板) |
| |
(反射 TS) |
獲取一個元物件序列型別,其元素反映被反射函式的引數 (類模板) |
(反射 TS) |
檢查被反射函式的引數列表是否包含省略號引數 (類模板) |
(反射 TS) |
檢查被反射函式是否不丟擲異常 (類模板) |
(反射 TS) |
檢查被反射函式是否已刪除 (類模板) |
| |
(反射 TS) |
檢查被反射變數或函式是否為 constexpr (類模板) |
| |
(反射 TS) |
檢查被反射名稱空間或函式是否為 inline (類模板) |
| |
(反射 TS) |
獲取反映被反射帶括號表示式的無括號表示式的元物件型別 (類模板) |
| |
(反射 TS) |
獲取反映被反射 函式呼叫表示式 中函式的元物件型別 (類模板) |
| |
(反射 TS) |
獲取反映被反射 函式式型別轉換表示式 中建構函式的元物件型別 (類模板) |
| |
(反射 TS) |
獲取被反射變數或函式的地址,或指向被反射非靜態成員的成員指標值 (類模板) |
| |
分別檢查被反射成員函式是否聲明瞭 const、volatile、& 或 && 限定符 (類模板) | |
(反射 TS) |
檢查被反射成員函式是否覆蓋基類的成員函式 (類模板) |
| |
(反射 TS) |
檢查被反射類或成員函式是否用 final 標記 (類模板) |
| |
(反射 TS) |
檢查被反射變數是否為靜態儲存期,或者被反射成員函式是否為靜態的 (類模板) |
| |
(反射 TS) |
檢查被反射的特殊成員函式是否是隱式宣告的 (類模板) |
(反射 TS) |
檢查被反射的特殊成員函式在其第一次宣告時是否已預設 (類模板) |
| |
(反射 TS) |
檢查被反射的建構函式或轉換函式是否用 explicit 宣告 (類模板) |
| |
(反射 TS) |
檢查被反射的成員函式是否為虛擬函式 (類模板) |
(反射 TS) |
檢查被反射的成員函式是否為純虛擬函式 (類模板) |
| |
(反射 TS) |
獲取一個元物件序列型別,其元素反映被反射閉包型別的捕獲 (類模板) |
檢查被反射閉包型別的 lambda 表示式的捕獲預設值是 = 還是 & (類模板) | |
(反射 TS) |
檢查被反射閉包型別的 operator() 是否用 const 宣告(類模板) |
| |
(反射 TS) |
檢查被反射的 lambda 捕獲是否顯式捕獲 (類模板) |
(反射 TS) |
檢查被反射的 lambda 捕獲是否是初始化捕獲 (類模板) |
[編輯] 庫特性測試宏
定義於標頭檔案
<experimental/reflect> | |
__cpp_lib_reflection (反射 TS) |
值至少為 201902 表示支援反射 TS 的支援庫 (宏常量) |
[編輯] 概念的滿足
下表列出了反映運算元的元物件型別是否滿足反射 TS 引入的概念。
分類 | reflexpr 運算元 |
滿足的概念 |
---|---|---|
型別 | 指定 聯合體 的 類名 | reflect::Union
|
指定 閉包型別 的 類名 | reflect::Lambda
| |
指定非聯合類的 類名 | reflect::Record
| |
列舉名 | reflect::Enum
| |
模板 型別引數 | reflect::Type , reflect::Alias | |
decltype-說明符 | reflect::Type , reflect::Alias | |
透過 using-宣告 引入的 型別名 | reflect::Type , reflect::Alias , reflect::ScopedMember | |
任何其他 typedef-名 | reflect::Type , reflect::Alias | |
任何其他 型別標識 | reflect::Type
| |
Namespace | 命名空間別名 | reflect::Namespace , reflect::Alias |
全域性名稱空間 | reflect::GlobalScope
| |
任何其他名稱空間 | reflect::Namespace
| |
Expression | 資料成員的名稱 | reflect::Variable
|
變數的名稱 | reflect::Variable
| |
列舉器的名稱 | reflect::Enumerator
| |
函式引數的名稱 | reflect::FunctionParameter
| |
捕獲實體的名稱 | reflect::LambdaCapture
| |
帶括號的表示式 | reflect::ParenthesizedExpression
| |
函式呼叫表示式 | reflect::FunctionCallExpression
| |
函式式型別轉換表示式 | reflect::FunctionalTypeConversion
|
如果 id-expression 形式的運算元是常量表達式,則由 reflexpr-說明符指定的型別也滿足 `reflect::Constant`。
如果 reflexpr-運算元指定類成員,則由 reflexpr-說明符表示的型別也滿足 `reflect::RecordMember`。
[編輯] 另請參閱
包含某些型別資訊的類,由 typeid 運算子返回 (類) | |
(C++11) |
編譯時型別資訊工具 |