title: 8.6.11&12 模板编程 tags: notebook: 8.0 工作准备
一、 模板概念
C++ 的抽象机制
- 面向对象:要了解编译知识
- 泛型编程:设计通用的类型或算法
- 元编程:使用模板进行选择和迭代,通过模板设计程序
模板多态
二、泛型编程
函数模板
匹配优先级:先匹配普通函数,再匹配特化模板函数,最后是通用模板函数。
模板函数
template<typename T>
void add(T a, T b) {
...
}
特化模板
template<typename T>
void add(T a, T b) {
...
}
template<>
void add(int a, int b) {
...
}
返回值类型
- C++14可以用auto进行返回值推导
- C++11 可以用decltype( )进行类型推导,返回是类型
template<typename T, typename U>
auto add(T a, T b)->decltype(a + b) {
return a + b;
}
T&&
万能的引用传递
- 在模板函数中,类型为左值引用
- 配合std::forward<T>( )使用,可以转换为传进来的类型
- 如何把模板的左值引用改为普通左值类型
typename std::remove_reference<T>::type c = a;
模板类
模板类
template<typename U>
class Print
{
}
模板类的特化
template<>
class Print<int>
变参模板
定义方式
template<class T, class ...ARGS>
void print(T& t, ARGS ...args) {
}
三、元编程
图灵完备性
- 要有基本的数据类型
- 需要某种方法,将基础的类型组合起来
- 需要流程控制。例如顺序、分支、循环
- 需要输入、输出。
编译时处理的变量
练习1
#include <iostream>
using namespace std;
template<int N>
struct mySum {
static constexpr int value = \
mySum<N - 1>::value + N;
};
template<>
struct mySum<0> {
static constexpr int value = 0;
};
int main(int argc, char const *argv[]) {
cout << mySum<100>::value << endl;
return 0;
}
四、类型萃取
#include <iostream>
#include <vector>
using namespace std;
template<class iter>
typename iter::value_type MySum(iter b, iter e) {
typename iter::value_type res{0};
for (iter i = b; i != e; i++) {
res += *i;
}
return res;
}
template<typename iter>
struct transType {
using value_type = typename iter::value_type;
};
template<typename iter>
struct transType<iter*> {
using value_type = iter;
};
template<class iter>
typename transType<iter>::value_type MySum2(iter b, iter e) {
typename transType<iter>::value_type res{0};
for (iter i = b; i != e; i++) {
res += *i;
}
return res;
}
int main(int argc, char const *argv[])
{
vector<int> arr{1, 2, 3, 54, 7};
cout << MySum(arr.begin(), arr.end()) << endl;
int arr2[] = {1,2,4,5,4124};
cout << MySum2(arr2, arr2 + 5) << endl;
return 0;
}
其他
- 模板不能写在cpp中
- 模板类成员方法不能用虚函数
- 虚函数表是在编译中生成
- 如果使用模板,则.h文件会遍历所有cpp文件,做不到
|