函式宣告
函式宣告引入函式名及其型別。函式定義將函式名/型別與函式體關聯起來。
目錄 |
[編輯] 函式宣告
函式宣告可以出現在任何作用域中。類作用域中的函式宣告引入一個類成員函式(除非使用了 friend 說明符),詳情請參見成員函式和友元函式。
noptr-declarator ( parameter-list ) cv (可選) ref (可選) except (可選) attr (可選) |
(1) | ||||||||
noptr-declarator ( parameter-list ) cv (可選) ref (可選) except (可選) attr (可選)-> trailing |
(2) | (C++11 起) | |||||||
(declarator 語法的其他形式請參見宣告)
noptr-declarator | - | 任何有效的 declarator,但如果它以 * 、& 或 && 開頭,則必須用括號括起來。 | ||||||
parameter-list | - | 可能為空的,逗號分隔的函式引數列表(詳情請參見下文) | ||||||
屬性 | - | (C++11 起) 一個屬性列表。這些屬性應用於函式型別,而非函式本身。函式的屬性出現在宣告符中識別符號之後,並與宣告開頭出現的任何屬性(如果有)相結合。 | ||||||
cv | - | const/volatile 限定符,僅允許在非靜態成員函式宣告中使用 | ||||||
ref | - | (C++11 起) ref 限定符,僅允許在非靜態成員函式宣告中使用 | ||||||
異常規範 | - |
| ||||||
trailing | - | 尾隨返回型別,在返回型別取決於引數名時很有用,例如 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-qualified 物件型別作為引數型別或返回型別已被棄用。 |
(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 引數被命名 | inf 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 起)。在這種情況下,選擇是在宣告一個函式指標型別的引數和宣告一個在 declarator 識別符號周圍有冗餘括號的引數之間。解決方案是將型別名視為簡單型別說明符(即函式指標型別)
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 前)否則,函式的(C++17 起)型別為
“derived-declarator-type-list function of
parameter-type-list cv (可選) ref (可選)(C++11 起) returningT
”。
在語法 (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 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 起) 屬性列表。這些屬性與 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 | - | 成員初始化列表,僅允許在建構函式中使用 |
複合語句 | - | 由一對花括號包圍的語句序列,構成函式的主體 |
function-try-block | - | 一個函式 try 塊 |
string-literal | - | 一個未求值字串字面量,可用於解釋函式被刪除的原因 |
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 起),並且不得有預設實參。 顯式預設特殊成員函式
如果
一個在其首次宣告時被顯式預設的函式是隱式 inline 的,如果它可以是一個 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 起),則該函式被定義為顯式刪除。 任何使用已刪除函式的行為都是非良構的(程式將無法編譯)。這包括呼叫(顯式呼叫運算子和隱式呼叫已刪除的過載運算子、特殊成員函式、分配函式等)、構造指向已刪除函式的指標或成員指標,甚至是在非潛在求值的表示式中使用已刪除函式。 非純虛成員函式可以定義為已刪除,即使它被隱式 odr-used。已刪除函式只能被已刪除函式覆蓋,非已刪除函式只能被非已刪除函式覆蓋。
如果函式被過載,則首先進行過載決議,並且只有在選擇了已刪除函式時,程式才非良構。 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 使用者提供函式一個函式如果在其首次宣告時是使用者宣告的,且未被顯式預設或刪除,則它是使用者提供的。一個使用者提供的顯式預設函式(即,在其首次聲明後顯式預設)在其被顯式預設的地方定義;如果這樣的函式被隱式定義為已刪除,則程式非良構。在其首次聲明後將函式宣告為預設可以提供高效執行和簡潔定義,同時為不斷演進的程式碼庫啟用穩定的二進位制介面。 // 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,則程式非良構。 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++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
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-use 是非良構的 已刪除虛擬函式的隱式odr-use是格式錯誤的 |
此類 odr-use 免於使用禁止 此類odr-use不受禁止 |
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 文件 關於 宣告函式
|