Template是编译时多态。所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态。
Function Template
A function template is a prescription for the compiler to generate particular instances of a function varying by type.
”变量类型“的部分放在一块,与“变量类型无关”的部分放在另一边。
放在"头文件“中,声明和实现建议这么做。其他方式不推荐。
Name Resolution
- designer & client
- Only three kinds of implicit conversions for type parameters:
参数的类型不同的数字比较的话,例如:int , double
使用例如:min(static_cast<double> i, d)的方式。
decltype (不用类型转换,编译器自己推导)
编译时类型推导,除了我们说过的auto关键字,还有本文的decltype。
(1) 解决模板函数返回值不确定情况:
template <typename T, typename U> auto mymin(T a, U b) -> decltype(a < b ? a : b) { return a < b ? a: b; }
泛型编程中结合auto,用于追踪函数的返回值类型!
(2) 根据变量推导齐类型:
int i; const &j = i; int *p = i; int k; decltype(i) x; // int x: i is a variable decltype(j) y = k; // int &y = k: j is an lvalue decltype(*p) z = k; // int &z = k: *p is an lvalue decltype((i)) w = k; // int &w = k: (i) is an lvalue
Ref: C++11特性:decltype关键字
(3) 与using/typedef合用,用于定义类型:
using size_t = decltype(sizeof(0));//sizeof(a)的返回值为size_t类型 using ptrdiff_t = decltype((int*)0 - (int*)0); using nullptr_t = decltype(nullptr);
vector<int >vec; typedef decltype(vec.begin()) vectype; for (vectype i = vec.begin; i != vec.end(); i++) { //... }
(4) 重用匿名类型:
在C++中,我们有时候会遇上一些匿名类型,而借助decltype,我们可以重新使用这个匿名的结构体:
struct { int d ; doubel b; }anon_s;
decltype(anon_s) as ; //定义了一个上面匿名的结构体
decltype推导四规则
- 如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么的decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译错误。
- 否则 ,假设e的类型是T,如果e是一个将亡值,那么decltype(e)为T&&
- 否则,假设e的类型是T,如果e是一个左值,那么decltype(e)为T&。
- 否则,假设e的类型是T,则decltype(e)为T。
注意小括号的作用:
int func(void) { int i = 10; decltype(i) a = i; decltype((i)) b = i; a = 10; cout << "i = " << i << endl; b = 20; // b变为 引用 cout << "i = " << i << endl; return 0; }
int decipline(void) { int i = 4; int arr[5] = { 0 }; int *ptr = arr; struct S{ double d; }s ; // void Overloaded(int); // void Overloaded(char);//重载的函数 int && RvalRef(); const bool Func(int); //规则一:推导为其类型 decltype (arr) var1; //int 标记符表达式 decltype (ptr) var2;//int * 标记符表达式 decltype(s.d) var3;//doubel 成员访问表达式 //decltype(Overloaded) var4;//重载函数。编译错误。 //规则二:将亡值。推导为类型的右值引用。 decltype (RvalRef()) var5 = 1; //规则三:左值,推导为类型的引用。 decltype ((i))var6 = i; //int& decltype (true ? i : i) var7 = i; //int& 条件表达式返回左值。 { int x = 10; float y = 1.11; decltype(true?x:y) c = (false?x:y); cout << "c = " << c << endl; } decltype (++i) var8 = i; //int& ++i返回i的左值。 decltype(arr[5]) var9 = i;//int&. []操作返回左值 decltype(*ptr)var10 = i;//int& *操作返回左值 decltype("hello")var11 = "hello"; //const char(&)[9] 字符串字面常量为左值,且为const左值。 //规则四:以上都不是,则推导为本类型 decltype(1) var12;//const int decltype(Func(1)) var13=true;//const bool decltype(i++) var14 = i;//int i++返回右值 return 0; }
四个规则的示例
左值推导为类型的引用:如何判断是否是左值呢?
cout << is_lvalue_reference<decltype(++i)>::value << endl;
模板的健壮性
若要比较字符串,使用函数override.
const char *s = "xyz"; const char *t = "abc"; /* 返回了数字,认为是地址,也就是数组的首地址 */ cout << min(s, t) << endl;
模板的设计 更加健壮。如下:
template function的默认参数 也可以设置,实现健壮性:
template‘s variadic function ,进一步健壮:
注意关键写法:
template <typename A, typename... B> void print(A head, B... tail) { ... }
continue...
时间: 2024-10-23 01:27:27