屬性說明符序列 (自 C++11 起)
為型別、物件、程式碼等引入實作定義 (implementation-defined) 的屬性。
目錄 |
[編輯] 語法
[[ attribute-list ]] |
(C++11 起) | ||||||||
[[ using attribute-namespace : attribute-list ]] |
(自 C++17 起) | ||||||||
其中 attribute-list 是由逗號分隔的零個或多個 attribute 組成的序列(結尾可選以省略號 ... 表示參數包展開)
| 識別字 | (1) | ||||||||
attribute-namespace :: identifier |
(2) | ||||||||
identifier ( argument-list (可選) ) |
(3) | ||||||||
attribute-namespace :: identifier ( argument-list (可選) ) |
(4) | ||||||||
其中 attribute-namespace 是一個 identifier,而 argument-list 是符記(token)序列,其中括號、中括號和大括號必須成對平衡(balanced-token-seq)。
|
若 [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]] [[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute |
(自 C++17 起) |
[編輯] 說明
屬性為實作定義的語言擴充功能提供了統一的標準語法,例如 GNU 和 IBM 的語言擴充 __attribute__((...))、微軟擴充 __declspec() 等。
屬性幾乎可以用在 C++ 程式的任何地方,並且幾乎可以應用於所有事物:型別、變數、函式、名稱、程式碼區塊、整個轉譯單元。儘管如此,每個特定的屬性僅在其被實作允許的地方才有效:例如 [[expect_true]] 可能是一個只能與 if 搭配使用的屬性,而不能用於類別宣告。[[omp::parallel()]] 可能是一個應用於程式碼區塊或 for 迴圈的屬性,但不能應用於型別 int 等(請注意這兩個屬性皆為虛構範例,標準及部分非標準屬性請參閱下文)。
在宣告中,屬性可以出現在整個宣告之前,也可以直接出現在所宣告實體的名稱之後,在此情況下兩者會合併。在大多數其他情況下,屬性適用於其直接前置的實體。
alignas 說明符是屬性說明符序列的一部分,儘管其語法不同。它可能出現在 [[...]] 屬性出現的地方,並可與它們混合使用(前提是使用位置允許 alignas)。
兩個連續的左方括號符記 ([[) 僅可在引入屬性說明符或在屬性參數內部時出現。
void f() { int y[3]; y[[] { return 0; }()] = 1; // error int i [[cats::meow([[]])]]; // OK }
除了下列標準屬性外,實作可能支援具有實作定義行為的任意非標準屬性。所有實作未知的屬性都會被忽略,且不會導致錯誤。(自 C++17 起)
|
沒有 attribute-namespace 的屬性,以及名稱為 |
(自 C++20 起) |
[編輯] 標準屬性
以下屬性由 C++ 標準定義。
標準屬性在語法上不可被忽略:它們不能包含語法錯誤、必須應用於正確的目標,且參數中的實體必須進行 ODR 使用 (ODR-use)。
標準屬性在語意上也不可被忽略:移除特定標準屬性的所有實例後,其行為仍必須與原始程式包含該屬性時的行為保持一致。
[[noreturn]](C++11) |
指示函式不會返回。 (屬性說明符) |
| (C++11)(於 C++26 移除) |
指示 release-consume std::memory_order 中的依賴鏈會在函式進出時傳遞。 (屬性說明符) |
[[deprecated]][[deprecated("reason")]](C++14)(C++14) |
指示該名稱或以該屬性宣告的實體是允許使用的,但基於某些 reason(原因)而不建議使用。 (屬性說明符) |
[[fallthrough]](C++17) |
指示從前一個 case 標籤落入 (fall through) 是刻意為之,且編譯器若有提供關於落入行為的警告,則不應對此發出診斷。 (屬性說明符) |
[[maybe_unused]](C++17) |
若存在未使用的實體,則抑制相關的編譯器警告。 (屬性說明符) |
| 鼓勵編譯器在回傳值被丟棄時發出警告。 (屬性說明符) | |
| 指示編譯器應針對執行路徑中某個語句比其他執行路徑更可能或更不可能發生的情況進行最佳化。 (屬性說明符) | |
| (C++20) |
指示非靜態資料成員無需擁有與其類別中所有其他非靜態資料成員不同的位址。 (屬性說明符) |
[[assume(expression)]](C++23) |
指定在給定點,expression(表達式)的值永遠會被評估為 true。 (屬性說明符) |
[[indeterminate]](C++26) |
指定若物件未被初始化,則其具有不確定值。 (屬性說明符) |
| (TM TS) |
指示函式定義應針對從同步語句 (synchronized statement) 的呼叫進行最佳化。 (屬性說明符) |
[編輯] 附註
可透過 __has_cpp_attribute 前置處理器巨集來檢查給定平台上各個屬性的存在與否。
| 特性測試巨集 | 數值 | 標準 | 功能 |
|---|---|---|---|
__cpp_attributes |
200809L |
(C++11) | 屬性 |
__cpp_namespace_attributes |
201411L |
(C++17) | 命名空間的屬性 |
[編輯] 範例
[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]] inline int f(); // declare f with four attributes [[gnu::always_inline, gnu::const, gnu::hot, nodiscard]] int f(); // same as above, but uses a single attr specifier that contains four attributes // C++17: [[using gnu : const, always_inline, hot]] [[nodiscard]] int f[[gnu::always_inline]](); // an attribute may appear in multiple specifiers int f() { return 0; } int main() {}
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。
| DR | 應用於 | 出版時的行為 | 正確的行為 |
|---|---|---|---|
| CWG 2079 | C++11 | [[ 不得出現在屬性參數內部 |
已允許 |
| CWG 2538 | C++11 | 標準屬性在語法上是否可被忽略是不明確的 | 禁止 |
| CWG 2695 | C++11 | 標準屬性在語意上是否可被忽略是不明確的 | 禁止 |
| P2156R1 | C++11 | 每個標準屬性在 attribute-list 中最多只能出現一次 | 不再需要 |
[編輯] 參見
__has_cpp_attribute - 檢查屬性是否存在 | |
| C 文件 關於 屬性說明符序列 (Attribute specifier sequence)
|
[編輯] 外部連結
| 1. | GCC 中的屬性。這些屬性可作為 [[gnu::...]] 使用,參見 SO。 |
| 2. | Clang 中的屬性. |
| 3. | MSVC 中的屬性. |