Function
Overview
C++的函数声明介绍了函数的名称和函数的类型,而函数的定义是将函数的声明和函数体关联起来。
Function Declaration
函数声明能够出现在任何Scope内。如果函数声明出现在class scope内(除了使用friend specifier),则该函数称为member functions,函数类型是由return type(符合declaration syntax的decl-specifier-seq)和function declarator组成的。
noptr-declaratorhello ( parameter-list ) cv(optional) ref(optional) except(optional) attr(optional) (1)
noptr-declarator ( parameter-list ) cv(optional) ref(optional) attr(optional) ->trailing (2)
(1) 普通的函数声明语法
(2) 尾部返回类型声明:尾部返回类型只允许在函数声明的最外层,这种情况下decl-specifier-seq只能是关键字 auto
noptr-declarator | - | 任何合理的declarator,但是以*,&或者&&为开头的必须用括号包围 | ||||
parameter-list | - | 可能为空,以逗号分隔的函数参数列表 | ||||
attr(C++11) | - | 可选的attributes列表,这些属性应用于函数类型,而不是函数本身。函数的属性出现在函数的声明符中的标识符之后,并且和出现在声明开头的属性结合(如果有的话)。 | ||||
cv | - | const/volatile限定,只允许出现在no-static member function声明中 | ||||
ref(C++11) | - | ref-qualification(引用限定),只允许出现在no-static member function声明中 | ||||
except | - | dynamic exception specification(Until C++2017)或者noexcept specification(C++11).注意exception specification(异常规范)并不是函数类型的一部分(Until C++17) | ||||
trailing (C++11) | - |
Trailing return type(尾置返回类型),如果返回值依赖于参数名字,将会非常有用,比如
|
// 声明一个 int, int*, 一个函数,一个指向函数的指针
int i, *p = NULL, f(), (*pf)(double);
// decl-specifier-seq 是int
// 声明符f声明(并非定义)了一个返回值为int,参数列表为空的函数
struct S {
virtual int f(char) const, g(int) &&; // 定义了两个 non-static member function
virtual int f(char), x; // 编译期错误:virtual(in decl-specifier-seq)只允许出现在
// non-static member function的声明中
};
使用volatile-qualified object 作为参数类型或者返回类型已经被废弃(Since C++20)
|
|
|
|
Return type deduction
如果 decl-specifier-seq 包含了 auto 关键字,尾部返回类型可能会被忽略,返回类型将会被编译器推断通过返回语句的表达式,如果返回类型并未使用 decltype(auto) ,则推断将会符合template argument deduction
int x = 1;
auto f() { return x; } // return type is int
const auto& f() { return x; } // return type is const int&
如果返回类型是decltype(auto),返回类型应与包装在decltype的表达式返回的类型相同.
int x = 1;
decltype(auto) f() { return x; } // return type is int, is same as decltype(x)
decltype(auto) f() { return (x); } // return type is int&, is same as decltype((x))
auto f(bool val)
{
if (val) return 123; // deduces return type int
else return 3.14f; // error: deduces return type float
}
如果没有返回语句或者返回语句返回 void expression ,声明的返回类型必须为 decltype(auto) ,在这种情况下,则推断返回类型为 void ,或者(可能 cv-qulified ) auto ,在这种情况下,则推断返回类型为 void (相同的 cv-qulified ) void
auto f() { } // returns void
auto g() { return f(); } // returns void
auto* x() { } // error: can't deduce auto* from void
一旦函数的返回语句出现,那么返回类型推断能够用于该函数剩余的部分,包括在其他返回语句当中.
auto sum(int i)
{
if (i == 1)
{
return i; // sum's return type is int
}
else
{
return sum(i - 1) + i; // okay: sum's return type is already known
}
}
如果返回语句包含 brace-init-list ,推断是不被允许的.
auto func() { return {1, 2, 3}; } // error
Virtual functions和coroutines(Since C++20)
struct F
{
virtual auto f() { return 2; } // error
}
如果一个函数使用return type deduction,那么该函数不能使用推断的类型重新声明或者另一种类型return type deduction的声明即使它推断的是相同的类型.
auto f(); // declared, not yet defined
auto f() { return 42; } // defined, return type is int
int f(); // error: can't use deduced type
decltype(auto) f(); // error: different kind of deduction
auto f(); // okay: re-declared
template<typename T>
struct A { friend T frf(T); }
auto frf(int i) { return i; } // not a friend of A<int>
除了用户自定义的转换函数外的{< better-anchor href=“/” hint=“Function templates”>}}都能使用return type deduction.推断发生在实例化,即使在返回语句中的表达式是独立的,该实例化不是即时的上下文对于SFINAE的期望.
template<typenmae T> auto f(T t) { return t; }
typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
template<typename T> auto f(T* t) { return *t; }
void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types.
// choose second template overload
特例化的函数模板使用return type deduction必须使用相同的返回类型占位符
template<typename T> auto g(T t) { return t; } // #1
template auto g(int); // okay: return type is int.
// template char g(char); error: no matching template
template<> auto g(double); // okay: forward declaration with unknown return type
template<typename T> T g(T t) { return t; } // okay: is not equivalent to #1
template char g(char); // okay: now is matching template
template auto g(float); // still matchs #1
// void h() { return g(42); } // error: ambiguous
显式化声明本身不会实例化使用return type deduction的函数模板.
template<typename T> auto f(T t) { return t; }
extern template auto f(int t); // does not instantiates 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