2026/3/5 0:36:27
网站建设
项目流程
做网站用的什么空间,天津建设工程信息网怎么报名,wordpress防采集,常平网站仿做函数模板形如#xff1a;
templatetypename T
void f(ParamType param);一次调用形如#xff1a;
f(expr); //以某表达式调用 f在编译期#xff0c;编译器会通过expr推导T的类型和ParamType的类型#xff08;通常会包含一些修饰#xff0c;例如const或引用符号…函数模板形如templatetypename T void f(ParamType param);一次调用形如f(expr); //以某表达式调用 f在编译期编译器会通过expr推导T的类型和ParamType的类型通常会包含一些修饰例如const或引用符号等限定。T的类型推导结果分以下三种情况讨论1.ParamType具有指针或引用型别但不是万能引用类型推导规则如下若expr具有引用类型先将引用部分忽略。然后对expr的类型和ParamType的类型执行模式匹配来决定T的类型。举例模式声明如下templatetypename T void f(T param); // param 是个引用声明下列变量int x 27; // x 的类型是 int const int xx x; // cx 的类型是 const int const int rx x; // rx 是 x 的类型为 const int 的引用各次调用的推导结果如下f(x); // T 的类型是 intparam 的类型是 int f(cx); // T 的类型是 const intparam 的类型是 const int f(rx); // T 的类型是 const intparam 的类型是 const int右值和指针方式同理templatetypename T void f(T* param); // param 是个指针 int x 27; const int *px x; // px 是指向 x 的指针类型为 const int f(x); // T 的类型是 int, param 的类型是 int* f(px); // T 的类型是 const int, param 的类型是 const int*2.ParamType是万能引用类型推导规则如下如果expr是个左值T和ParamType都会被推导为左值引用。如果expr是个右值则应用“常规即情况 1 中的规则。举例templatetypename T void f(T param); // param 是个万能引用 int x 27; const int cx x; const int rx x; f(x); // x 是个左值所以 T 的类型是 int, param 的类型也是 int f(cx); // cx 是个左值所以 T 的类型是 const int, param 的类型也是 const int f(rx); // rx 是个左值所以 T 的类型是 const int, param 的类型也是 const int f(27); // 27 是个右值所以 T 的类型是 int, param 的类型就成了 int3.ParamType既非指针也非引用即按值传递无论传入的是什么param都会是它的副本是一个新对象若expr具有引用类型则忽略其引用部分。忽略expr的引用性之后若expr是个const对象也忽略。若其是个volatile对象同样忽略。举例templatetypename T void f(T param); //param现在是按值传递 int x 27; //同前 const int cx x; //同前 const int rx x; //同前 f(x); // T和param的类型都是int f(cx); // T和param的类型都是int f(rx); // T和param的类型都是int即使cx和rx代表const值param仍然不具有const的类型。param是个完全独立于cx和rx的一个副本。从而cx和rx不可修改并不能说明param是否可以修改。数组实参一种边缘情况数组类型有别于指针类型但是在多数语境下数组会退化成首元素的指针。C 中没有真正的“数组形参”因为函数无法直接接收数组当数组传递给按值形参的模板时编译器会把形参里的数组声明直接当作指针处理。但是尽管函数无法声明真正的数组类型的形参但是它们能够将形参声明为数组的引用。在这种情况下T的类型会被推导成实际的数组类型。这个类型中会包含数组尺寸。利用声明数组引用能力可以创造出一个模板用来推导数组中含有的元素个数// 以编译期常量形式返回数组尺寸 // 该数组形参未起名字因为我们只关心共含有的元素个数 templatetypename T, std::size_t N constexpr std::size_t arraySize(T ()[N]) noexcept { return N; }将函数声明为constexpr能够使得其返回值在编译期就可以使用。从而在声明一个数组时指定其尺寸和另一数组相同而后者的尺寸则从花括号初始化形式计算得出int keyVals[] { 1, 3, 7, 9, 11, 22, 35 }; // keyVals 含有 7 个元素 int mappedVals [arraySize(keyVals)]; // mappedVals 被指定与之相同函数实参函数类型也同样会退化成函数指针并且针对数组类型推导的一切都适用于函数及其向函数指针的退化。如下void someFunc(int, double); // someFunc 是个函数其类型为 void(int, double) templatetypename T void f1(T param); // 在 f1 中param 按值传递 templatetypename T void f2 (T param); // 在 f2 中param 按引用传递 f1(someFunc); // param 披推导为函数指针具体类型是 void (*)(int, double) f2(someFunc); // param 披推导为函数引用具体类型是 void ()(int, double)总结在模板类型推导时有引用的实参会被视为无引用它们的引用会被忽略对于通用引用的推导左值实参会被特殊对待对于传值类型推导const/volatile实参会被认为是non-const的和non-volatile的在模板类型推导时数组名或者函数名实参会退化为指针除非它们被用于初始化引用原著在线阅读地址