函式宣告
函式宣告引入函式名稱及其型別。函式定義將函式名稱/型別與函式主體關聯起來。
目錄 |
[編輯] 函式宣告
函式宣告可以出現在任何作用域中。類別作用域中的函式宣告引入一個類別成員函式 (除非使用 friend 指定符),詳情請參閱成員函式和友元函式。
noptr-declarator ( parameter-list ) cv (可選) ref (可選) except (可選) attr (可選) |
(1) | ||||||||
noptr-declarator ( parameter-list ) cv (可選) ref (可選) except (可選) attr (可選)-> trailing |
(2) | (C++11 起) | |||||||
(請參閱宣告以了解宣告子語法的其他形式)
| noptr-declarator | - | 任何有效的宣告子,但如果它以 *、& 或 && 開頭,則必須用括號括起來。 | ||||||
| 參數列表 | - | 函式參數的列表,可能為空,以逗號分隔 (詳情請參閱下文) | ||||||
| 屬性 | - | (C++11 起) 一個屬性列表。這些屬性應用於函式的型別,而非函式本身。函式的屬性出現在宣告子內的識別符之後,並與宣告開頭出現的屬性(如果有的話)合併。 | ||||||
| cv | - | const/volatile 限定,僅允許於非靜態成員函式宣告中 | ||||||
| ref | - | (C++11 起) ref 限定,僅允許於非靜態成員函式宣告中 | ||||||
| except | - |
| ||||||
| 尾部 | - | 尾部回傳型別,當回傳型別依賴於引數名稱時很有用,例如 template<class T, class U> auto add(T t, U u) -> decltype(t + u);;或當其複雜時,例如 auto fpif(int)->int(*)(int) |
|
如宣告中所述,宣告子可以後跟一個requires 子句,它宣告了函式的相關約束,這些約束必須被滿足,以便函式能被重載解析選中。(範例:void f1(int a) requires true;) 請注意,相關約束是函式簽章的一部分,但不是函式型別的一部分。 |
(自 C++20 起) |
函式宣告子可以與其他宣告子混合使用,只要宣告指定符序列允許。
// declares an int, an int*, a function, and a pointer to a function int a = 1, *p = NULL, f(), (*pf)(double); // decl-specifier-seq is int // declarator f() declares (but doesn't define) // a function taking no arguments and returning int struct S { virtual int f(char) const, g(int) &&; // declares two non-static member functions virtual int f(char), x; // compile-time error: virtual (in decl-specifier-seq) // is only allowed in declarations of non-static // member functions };
|
使用 volatile 限定的物件型別作為參數型別或回傳型別已被棄用。 |
(自 C++20 起) |
函式的回傳型別不能是函式型別或陣列型別(但可以是這些型別的指標或參考)。
|
如同任何宣告,出現在宣告之前的屬性以及緊接著識別符之後、宣告子之內的屬性都適用於被宣告或定義的實體(在此情況下,適用於函式) [[noreturn]] void f [[noreturn]] (); // OK: both attributes apply to the function f 然而,出現在宣告子之後(在上述語法中)的屬性,則應用於函式的型別,而非函式本身 void f() [[noreturn]]; // Error: this attribute has no effect on the function itself |
(C++11 起) |
回傳型別推導如果函式宣告的decl-specifier-seq包含關鍵字 auto,則可省略尾部回傳型別,編譯器將從 return 陳述式中使用的表達式型別推導出來。如果回傳型別不使用 decltype(auto),則推導遵循模板引數推導的規則 int x = 1; auto f() { return x; } // return type is int const auto& f() { return x; } // return type is const int& 如果回傳型別是 decltype(auto),則回傳型別與 int x = 1; decltype(auto) f() { return x; } // return type is int, same as decltype(x) decltype(auto) f() { return(x); } // return type is int&, same as decltype((x)) (注意:「const decltype(auto)&」是錯誤的,decltype(auto) 必須單獨使用) 如果有多個 return 陳述式,它們都必須推導為相同的型別 auto f(bool val) { if (val) return 123; // deduces return type int else return 3.14f; // Error: deduces return type float } 如果沒有 return 陳述式,或者 return 陳述式的引數是 void 表達式,則宣告的回傳型別必須是 decltype(auto),在這種情況下推導的回傳型別是 void;或者是 (可能 cv-限定的) auto,在這種情況下推導的回傳型別也是 (相同 cv-限定的) void auto f() {} // returns void auto g() { return f(); } // returns void auto* x() {} // Error: cannot deduce auto* from void 一旦函式中出現 return 陳述式,從該陳述式推導出的回傳型別可以在函式的其餘部分使用,包括其他 return 陳述式 auto sum(int i) { if (i == 1) return i; // sum’s return type is int else return sum(i - 1) + i; // OK: sum’s return type is already known } 如果 return 陳述式使用大括號初始器列表,則不允許推導 auto func() { return {1, 2, 3}; } // Error struct F { virtual auto f() { return 2; } // Error }; 函式模板,除了使用者定義轉換函式之外,可以使用回傳型別推導。推導發生在實例化時,即使 return 陳述式中的表達式不是依賴的。此實例化不屬於SFINAE目的的即時語境。 template<class T> auto f(T t) { return t; } typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type template<class T> auto f(T* t) { return *t; } void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types, // chooses second template overload 使用回傳型別推導的函式或函式模板的重新宣告或特化必須使用相同的回傳型別佔位符 auto f(int num) { return num; } // int f(int num); // Error: no placeholder return type // decltype(auto) f(int num); // Error: different placeholder template<typename T> auto g(T t) { return t; } template auto g(int); // OK: return type is int // template char g(char); // Error: not a specialization of the primary template g 同樣,不使用回傳型別推導的函式或函式模板的重新宣告或特化不得使用佔位符 int f(int num); // auto f(int num) { return num; } // Error: not a redeclaration of f template<typename T> T g(T t) { return t; } template int g(int); // OK: specialize T as int // template auto g(char); // Error: not a specialization of the primary template g 顯式實例化宣告本身不實例化使用回傳型別推導的函式模板 template<typename T> auto f(T t) { return t; } extern template auto f(int); // does not instantiate f<int> int (*p)(int) = f; // instantiates f<int> to determine its return type, // but an explicit instantiation definition // is still required somewhere in the program |
(C++14 起) |
[編輯] 參數列表
參數列表決定了函式被呼叫時可以指定的引數。它是一個以逗號分隔的參數宣告列表,每個參數宣告具有以下語法
| attr (可選) decl-specifier-seq declarator | (1) | ||||||||
|
attr (可選) |
(2) | (自 C++23 起) | |||||||
attr (可選) decl-specifier-seq declarator = initializer |
(3) | ||||||||
| attr (可選) decl-specifier-seq abstract-declarator (可選) | (4) | ||||||||
|
attr (可選) |
(5) | (自 C++23 起) | |||||||
attr (可選) decl-specifier-seq abstract-declarator (可選) = initializer |
(6) | ||||||||
void
|
(7) | ||||||||
| 錯誤用法 | 範例 |
|---|---|
| 存在多個參數 | int f1(void, int); |
| 命名了 void 參數 | int f2(void param); |
| void 被 cv-限定 | int f3(const void); |
| void 是依賴的 | int f4(T); (其中 T 是 void) |
| 該 void 參數是顯式物件參數 (C++23 起) | int f5(this void); |
|
儘管decl-specifier-seq暗示可以存在型別指定符以外的指定符,但唯一允許的其他指定符是 register 以及 auto(C++11 前),且它沒有作用。 |
(直到 C++17) |
|
如果函式參數中的任何一個使用了佔位符(auto 或 概念型別),則該函式宣告反而是一個簡寫函式模板宣告 void f1(auto); // same as template<class T> void f1(T) void f2(C1 auto); // same as template<C1 T> void f2(T), if C1 is a concept |
(自 C++20 起) |
|
帶有指定符 this 的參數宣告(語法 (2)/(5))宣告一個顯式物件參數。 顯式物件參數不能是函式參數包,且它只能作為參數列表的第一個參數出現在以下宣告中 帶有顯式物件參數的成員函式有以下限制 struct C { void f(this C& self); // OK template<typename Self> void g(this Self&& self); // also OK for templates void p(this C) const; // Error: “const” not allowed here static void q(this C); // Error: “static” not allowed here void r(int, this C); // Error: an explicit object parameter // can only be the first parameter }; // void func(this C& self); // Error: non-member functions cannot have // an explicit object parameter |
(自 C++23 起) |
函式宣告中宣告的參數名稱通常僅用於自我文件目的。它們在函式定義中使用(但仍是可選的)。
當型別名稱嵌套在括號中時,參數列表中會出現歧義(包括lambda 表達式)(C++11 起)。在這種情況下,選擇是在型別為函式指標的參數宣告與宣告子識別符周圍有多餘括號的參數宣告之間。解析方式是將型別名稱視為簡單型別指定符(即函式指標型別)
class C {}; void f(int(C)) {} // void f(int(*fp)(C param)) {} // NOT void f(int C) {} void g(int *(C[10])); // void g(int *(*fp)(C param[10])); // NOT void g(int *C[10]);
參數型別不能是包含參考或指向未知邊界陣列的指標的型別,包括此類型的多級指標/陣列,或指向參數為此類型的函式的指標。
[編輯] 使用省略符號
參數列表中的最後一個參數可以是省略符號 (...);這宣告一個可變引數函式。省略符號之前的逗號可以省略(C++26 起棄用)
int printf(const char* fmt, ...); // a variadic function int printf(const char* fmt...); // same as above, but deprecated since C++26 template<typename... Args> void f(Args..., ...); // a variadic function template with a parameter pack template<typename... Args> void f(Args... ...); // same as above, but deprecated since C++26 template<typename... Args> void f(Args......); // same as above, but deprecated since C++26
[編輯] 函式型別
[編輯] 參數型別列表
函式的參數型別列表按以下方式決定
- 每個參數的型別(包括函式參數包)(C++11 起)從其自身的參數宣告中決定。
- 在決定每個參數的型別後,任何型別為「T 的陣列」或函式型別 T 的參數將被調整為「指向 T 的指標」。
- 在產生參數型別列表後,在形成函式型別時,修飾參數型別的任何頂層cv-限定符會被刪除。
- 轉換後的參數型別列表,以及省略符號或函式參數包(C++11 起)的存在與否,即為函式的參數型別列表。
void f(char*); // #1 void f(char[]) {} // defines #1 void f(const char*) {} // OK, another overload void f(char* const) {} // Error: redefines #1 void g(char(*)[2]); // #2 void g(char[3][2]) {} // defines #2 void g(char[3][3]) {} // OK, another overload void h(int x(const int)); // #3 void h(int (*)(int)) {} // defines #3
[編輯] 判斷函式型別
在語法 (1) 中,假設 noptr-declarator 作為一個獨立的宣告,給定 noptr-declarator 中 qualified-id 或 unqualified-id 的型別為「derived-declarator-type-list T」
|
(自 C++17 起) |
- 函式的(C++17 前)否則,函式的(C++17 起)宣告型別為
「derived-declarator-type-list 函式,其
參數型別列表 cv (可選) ref (可選)(C++11 起) 回傳T」。
|
在語法 (2) 中,假設 noptr-declarator 作為一個獨立的宣告,給定 noptr-declarator 中 qualified-id 或 unqualified-id 的型別為「derived-declarator-type-list |
(C++11 起) |
|
(自 C++17 起) |
若存在attr,則其適用於函式型別。 |
(C++11 起) |
// the type of “f1” is // “function of int returning void, with attribute noreturn” void f1(int a) [[noreturn]]; // the type of “f2” is // “constexpr noexcept function of pointer to int returning int” constexpr auto f2(int[] b) noexcept -> int; struct X { // the type of “f3” is // “function of no parameter const returning const int” const int f3() const; };
[編輯] 尾部限定符
帶有 cv 或 ref (C++11 起) 的函式型別(包括由 typedef 名稱命名的型別)只能作為
- 用於非靜態成員函式的函式型別,
- 成員指標所指向的函式型別,
- 函式 typedef 宣告或別名宣告(C++11 起)的頂層函式型別,
- 模板型別參數的預設引數中的型別 ID,或
- 模板型別參數的模板引數的型別 ID。
typedef int FIC(int) const; FIC f; // Error: does not declare a member function struct S { FIC f; // OK }; FIC S::*pm = &S::f; // OK
[編輯] 函式簽章
每個函式都有一個簽章。
函式的簽章由其名稱和參數型別列表組成。其簽章還包含封閉的命名空間,但有以下例外情況
- 如果函式是成員函式,則其簽章包含函式所屬的類別而非封閉的命名空間。其簽章還包含以下組件(如果存在)
- cv
|
(C++11 起) |
|
(自 C++20 起) |
except和attr(C++11 起)不涉及函式簽章,儘管noexcept 規格會影響函式型別(C++17 起)。
[編輯] 函式定義
非成員函式定義只能出現在命名空間作用域(沒有巢狀函式)。成員函式定義也可以出現在類別定義的本體中。它們具有以下語法
| attr (可選) decl-specifier-seq (可選) declarator virt-specs (可選) contract-specs (可選) function-body |
(1) | ||||||||
| attr (可選) decl-specifier-seq (可選) declarator requires-clause contract-specs (可選) function-body |
(2) | (自 C++20 起) | |||||||
| 屬性 | - | (C++11 起) 一個屬性列表。這些屬性與宣告子中識別符之後的屬性(如果有的話,請參閱本頁頂部)合併。 |
| decl-specifier-seq (宣告說明符序列) | - | 帶有指定符的回傳型別,如同在宣告語法中一樣 |
| 宣告子 (declarator) | - | 函式宣告子,與上述函式宣告語法相同(可以加括號) |
| virt-specs | - | (C++11 起) override、final,或它們以任何順序組合 |
| requires-clause | - | 一個requires 子句 |
| contract-specs | - | (C++26 起) 一個函式合約指定符列表 |
| function-body | - | 函式主體(詳見下文) |
function-body 是以下之一
| ctor-initializer (可選) compound-statement | (1) | ||||||||
| function-try-block | (2) | ||||||||
= default ; |
(3) | (C++11 起) | |||||||
= delete ; |
(4) | (C++11 起) | |||||||
= delete ( string-literal ); |
(5) | (C++26 起) | |||||||
| ctor-initializer | - | 成員初始器列表,僅允許在建構函式中使用 |
| compound-statement | - | 構成函式主體的大括號括起來的陳述式序列 |
| function-try-block | - | 一個函式 try 區塊 |
| 字串字面值 | - | 一個未求值字串字面值,可用於解釋函式被刪除的原因 |
int max(int a, int b, int c) { int m = (a > b) ? a : b; return (m > c) ? m : c; } // decl-specifier-seq is “int” // declarator is “max(int a, int b, int c)” // body is { ... }
函式主體是一個複合陳述式(由一對大括號圍繞的零個或多個陳述式序列),在函式呼叫時執行。此外,建構函式的函式主體還包括以下內容
- 對於其識別符不在建構函式的成員初始器列表中的所有非靜態資料成員,用於初始化相應成員子物件的預設成員初始器或(C++11 起)預設初始化。
- 對於其型別名稱不在建構函式成員初始器列表中的所有基底類別,用於初始化相應基底類別子物件的預設初始化。
|
如果函式定義包含virt-specs,它必須定義一個成員函式。 |
(C++11 起) |
|
如果函式定義包含requires-clause,它必須定義一個模板化函式。 |
(自 C++20 起) |
void f() override {} // Error: not a member function void g() requires (sizeof(int) == 4) {} // Error: not a templated function
函式定義的參數型別和回傳型別不能是(可能 cv-限定的)不完整的類別型別,除非函式被定義為刪除(C++11 起)。完整性檢查僅在函式主體中進行,這允許成員函式回傳定義它們的類別(或其封閉類別),即使在定義點上它是不完整的(在函式主體中它是完整的)。
函式定義的declarator中宣告的參數在主體內是作用域內的。如果函式主體中未使用參數,則無需命名(使用抽象宣告子即可)
void print(int a, int) // second parameter is not used { std::printf("a = %d\n", a); }
儘管函式宣告中參數上的頂層cv-限定符被捨棄,但它們會修改在函式主體中可見的參數型別
void f(const int n) // declares function of type void(int) { // but in the body, the type of “n” is const int }
預設函式如果函式定義是語法 (3),則該函式被定義為顯式預設。 顯式預設的函式必須是特殊成員函式或比較運算符函式(C++20 起),且它不能有預設引數。 顯式預設的特殊成員函式
如果
在首次宣告時顯式預設的函式是隱式內聯的,如果它可以是 constexpr 函式,則它也是隱式 constexpr 的。 struct S { S(int a = 0) = default; // error: default argument void operator=(const S&) = default; // error: non-matching return type ~S() noexcept(false) = default; // OK, different exception specification private: int i; S(S&); // OK, private copy constructor }; S::S(S&) = default; // OK, defines copy constructor 顯式預設函式和隱式宣告函式統稱為預設函式。它們的實際定義將會隱式提供,詳情請參閱其對應頁面。 刪除函式如果函式定義是語法 (4)或 (5)(C++26 起),則該函式被定義為顯式刪除。 任何使用刪除函式的行為都是格式不正確的 (ill-formed)(程式將無法編譯)。這包括顯式呼叫(使用函式呼叫運算符)和隱式呼叫(呼叫已刪除的重載運算符、特殊成員函式、記憶體分配函式等),構造指向已刪除函式的指標或成員指標,甚至在不是潛在求值的表達式中使用已刪除函式。 非純虛擬成員函式可以被定義為刪除,即使它會被隱式地odr-使用。已刪除的函式只能被已刪除的函式覆蓋,而非刪除的函式只能被非刪除的函式覆蓋。
如果函式被重載,則首先進行重載解析,並且只有在選中已刪除函式時,程式才是格式不正確的 (ill-formed)。 struct T { void* operator new(std::size_t) = delete; void* operator new[](std::size_t) = delete("new[] is deleted"); // since C++26 }; T* p = new T; // Error: attempts to call deleted T::operator new T* p = new T[5]; // Error: attempts to call deleted T::operator new[], // emits a diagnostic message “new[] is deleted” 函式的刪除定義必須是翻譯單元中的第一個宣告:先前宣告的函式不能被重新宣告為刪除。 struct T { T(); }; T::T() = delete; // Error: must be deleted on the first declaration 使用者提供函式如果函式是使用者宣告的,且在其首次宣告時沒有顯式預設或刪除,則它被視為使用者提供的。使用者提供且顯式預設的函式(即在首次宣告之後顯式預設的函式)在其顯式預設點被定義;如果此類函式被隱式定義為刪除,則程式格式不正確 (ill-formed)。在首次宣告之後將函式宣告為預設,可以提供高效執行和簡潔定義,同時為不斷演進的程式碼庫啟用穩定的二進位介面。 // All special member functions of “trivial” are // defaulted on their first declarations respectively, // they are not user-provided struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~trivial() = default; }; struct nontrivial { nontrivial(); // first declaration }; // not defaulted on the first declaration, // it is user-provided and is defined here nontrivial::nontrivial() = default; 歧義解析在函式主體與以
using T = void(); // function type using U = int; // non-function type T a{}; // defines a function doing nothing U b{}; // value-initializes an int object T c = delete("hello"); // defines a function as deleted U d = delete("hello"); // copy-initializes an int object with // the result of a delete expression (ill-formed)
__func__在函式主體內,函式局部預定義變數 __func__ 的定義方式如同透過 static const char __func__[] = "function-name"; 此變數具有區塊作用域和靜態儲存期 struct S { S(): s(__func__) {} // OK: initializer-list is part of function body const char* s; }; void f(const char* s = __func__); // Error: parameter-list is part of declarator |
(C++11 起) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
函式合約指定符函式宣告和lambda 表達式可以包含一序列的函式合約指定符,每個指定符具有以下語法
1) 引入一個前置條件斷言。
2,3) 引入一個後置條件斷言。
2) 斷言不綁定到結果。
3) 斷言綁定到結果。
函式合約斷言是與函式相關聯的合約斷言。函式合約斷言的判斷式是其predicate語境轉換為 bool。 以下函式不能使用函式合約指定符宣告 前置條件斷言前置條件斷言與進入函式相關聯 int divide(int dividend, int divisor) pre(divisor != 0) { return dividend / divisor; } double square_root(double num) pre(num >= 0) { return std::sqrt(num); } 後置條件斷言後置條件斷言與函式正常退出相關聯。 如果後置條件斷言帶有identifier,則函式合約指定符會引入identifier作為相關函式結果綁定的名稱。結果綁定表示函式呼叫所回傳的物件或參考。結果綁定的型別是其相關函式的回傳型別。 int absolute_value(int num) post(r : r >= 0) { return std::abs(num); } double sine(double num) post(r : r >= -1.0 && r <= 1.0) { if (std::isnan(num) || std::isinf(num)) // exiting via an exception never causes contract violation throw std::invalid_argument("Invalid argument"); return std::sin(num); } 如果後置條件斷言帶有identifier,且相關函式的回傳型別是(可能 cv-限定的)void,則程式格式不正確 (ill-formed) void f() post(r : r > 0); // Error: no value can be bound to “r” 當非模板函式宣告的回傳型別包含佔位符型別時,帶有identifier的後置條件斷言只能出現在函式定義中 auto g(auto&) post(r : r >= 0); // OK, “g” is a template auto h() post(r : r >= 0); // Error: cannot name the return value auto k() post(r : r >= 0) // OK, “k” is a definition { return 0; } 合約一致性函式或函式模板 func 的重新宣告 如果宣告 如果兩個contract-specs由相同順序的函式合約指定符組成,則它們是相同的。 函式宣告
如果此條件未被滿足僅因為比較包含在predicate中的兩個 lambda 表達式,則不需要診斷。 bool b1, b2; void f() pre (b1) pre([]{ return b2; }()); void f(); // OK, function contract specifiers omitted void f() pre (b1) pre([]{ return b2; }()); // Error: closures have different types void f() pre (b1); // Error: function contract specifiers are different int g() post(r : b1); int g() post(b1); // Error: no result binding namespace N { void h() pre (b1); bool b1; void h() pre (b1); // Error: function contract specifiers differ // according to the one−definition rule } |
(C++26 起) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[編輯] 附註
在變數宣告使用直接初始化語法與函式宣告之間存在歧義的情況下,編譯器始終選擇函式宣告;請參閱直接初始化。
| 特性測試巨集 | 數值 | 標準 | 功能 |
|---|---|---|---|
__cpp_decltype_auto |
201304L |
(C++14) | decltype(auto)
|
__cpp_return_type_deduction |
201304L |
(C++14) | 普通函式的回傳型別推導 |
__cpp_explicit_this_parameter |
202110L |
(C++23) | 顯式物件參數(推導 this) |
__cpp_deleted_function |
202403L |
(C++26) | 帶有原因的刪除函式 |
[編輯] 關鍵字
[編輯] 範例
#include <iostream> #include <string> // simple function with a default argument, returning nothing void f0(const std::string& arg = "world!") { std::cout << "Hello, " << arg << '\n'; } // the declaration is in namespace (file) scope // (the definition is provided later) int f1(); // function returning a pointer to f0, pre-C++11 style void (*fp03())(const std::string&) { return f0; } // function returning a pointer to f0, with C++11 trailing return type auto fp11() -> void(*)(const std::string&) { return f0; } int main() { f0(); fp03()("test!"); fp11()("again!"); int f2(std::string) noexcept; // declaration in function scope std::cout << "f2(\"bad\"): " << f2("bad") << '\n'; std::cout << "f2(\"42\"): " << f2("42") << '\n'; } // simple non-member function returning int int f1() { return 007; } // function with an exception specification and a function try block int f2(std::string str) noexcept try { return std::stoi(str); } catch (const std::exception& e) { std::cerr << "stoi() failed!\n"; return 0; } // deleted function, an attempt to call it results in a compilation error void bar() = delete # if __cpp_deleted_function ("reason") # endif ;
可能輸出
stoi() failed!
Hello, world!
Hello, test!
Hello, again!
f2("bad"): 0
f2("42"): 42[編輯] 缺陷報告
下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。
| DR | 應用於 | 出版時的行為 | 正確的行為 |
|---|---|---|---|
| CWG 135 | C++98 | 類別中定義的成員函式 不能有參數或回傳 其自身的類別,因為它不完整 |
已允許 |
| CWG 332 | C++98 | 參數可以有 cv-限定的 void 型別 | 禁止 |
| CWG 393 | C++98 | 包含指標/參考到 未知邊界陣列的型別不能作為參數 |
允許此類別型別 |
| CWG 452 | C++98 | 成員初始器列表不屬於函式主體 | 現在是了 |
| CWG 577 | C++98 | 依賴型別 void 可以用於 宣告不帶參數的函式 |
只有非依賴的 void 是允許的 |
| CWG 1327 | C++11 | 預設或刪除函式不能 被指定為 override 或 final |
已允許 |
| CWG 1355 | C++11 | 只有特殊成員函式可以是使用者提供的 | 擴展到所有函式 |
| CWG 1394 | C++11 | 刪除函式不能有任何參數為 不完整型別或回傳不完整型別 |
允許不完整型別 |
| CWG 1824 | C++98 | 參數型別和 函式定義的回傳型別的完整性檢查可以 在函式定義語境之外進行 |
只在 函式定義的 語境中檢查 |
| CWG 1877 | C++14 | 回傳型別推導將 return; 視為 return void(); | 在此情況下,直接推導回傳 型別為 void |
| CWG 2015 | C++11 | 刪除函式的隱式 odr-使用 虛擬函式是格式不正確的 |
此類 odr-使用被豁免 使用限制 |
| CWG 2044 | C++14 | 回傳 void 的函式的回傳型別推導 如果宣告的回傳型別是 decltype(auto) 會失敗 |
更新推導 規則以處理此情況 |
| CWG 2081 | C++14 | 函式重新宣告可以使用回傳型別 推導,即使初始宣告沒有 |
不允許 |
| CWG 2144 | C++11 | {} 可能在同一位置是函式主體或初始器 | 透過類型區分 宣告子識別符的 |
| CWG 2145 | C++98 | 函式定義中的declarator不能加括號 | 已允許 |
| CWG 2259 | C++11 | 關於括號化型別名稱的歧義解析規則 未涵蓋 lambda 表達式 |
已涵蓋 |
| CWG 2430 | C++98 | 在類別定義中成員函式的定義中, 該類別的型別不能作為回傳型別或 參數型別,由於CWG 問題 1824 的解析 |
只在 函式主體 |
| CWG 2760 | C++98 | 建構函式的函式主體不包括初始值設定 在建構函式的常規函式主體中未指定 |
也包括這些 初始值設定 |
| CWG 2831 | C++20 | 帶有requires-clause的函式定義 可以定義非模板函式 |
禁止 |
| CWG 2846 | C++23 | 顯式物件成員函式不能有類外定義 | 已允許 |
| CWG 2915 | C++23 | 無名顯式物件參數可以有 void 型別 | 禁止 |
[編輯] 參閱
| C 語言文件中關於宣告函式
|