标签:
1 . 通用函数可变参数模板
对于有些时候,我们无法确切的知道,函数的参数个数时,而又不想过多的使用所谓的函数重载,那么就可以效仿下面的例子:
1 #include<iostream> 2 #include<Array> 3 void showall() { return; } 4 5 template <typename R1 ,typename... Args> 6 7 void showall(R1 var, Args...args) { 8 9 std::cout << var << std::endl; 10 showall(args...); 11 } 12 13 int main(int argc, char * args[]) { 14 15 16 showall(1, 2, 3, 4, 5); 17 showall("gxjun","dadw","dasds"); 18 showall(1.0,2.0,3.5); 19 std::cin.get(); 20 return 0; 21 }
在游戏开发中,时常会用到这样的模板,类型不确定,参数的个数不确定,所以需要用一种类似于递归的函数来处理。 第一个函数,表示的是在参数为0时,结束。
效果:
2. 如何使用仿函数:
首先仿函数的定义: ,仿函数也叫函数对象(Function Object, or Functor),定义就是任何可以像函数一样被调用的对象。一个普通的函数是函数对象,一个函数指针当然也是,广义上说任何定义了operator()的类对象都可以看作是函数对象。 (找到文档)
其实,往直白的地方说,就是一个不是函数但是具有函数功能且用法和函数相同的对象(结构体或者类)。
下面举个栗子(用结构体实现函数功能):
1 /*关于C++仿函数*/ 2 #include<iostream> 3 #include<functional> 4 using namespace std; 5 using namespace std::placeholders; 6 7 template <typename R1 , typename R2> 8 struct Calc 9 { 10 void add(R1 a) { 11 cout << a << endl; 12 }; 13 void add_1(R1 a, R1 b) { 14 cout << a + b << endl; 15 } 16 }; 17 18 int main(int argc, char * args[]) { 19 20 //函数指针 21 void(Calc<int, double>::*fc)(int a) = &Calc<int, double >::add; 22 // fc(25); 23 //显然上面的式子比较的麻烦 24 25 Calc < int, int> calc; 26 auto fun = bind(&Calc<int, int >::add, &calc, _1); 27 auto fun_2 = bind(&Calc<int, int >::add_1, &calc, _1,_2); 28 fun(123); 29 fun_2(12,24); 30 cin.get(); 31 return 0; 32 }
对于bind()这个函数,开头的是地址,函数名,后面的是第一个列子中的Args....不定参数类型、
效果图为:
3. 使用using别名,函数指针,typdef来实现函数的调用
虽然是寥寥的几行代码,但是功能在实际应用中,却会发挥很大的作用。
1 //using别名使用用法 2 #include<iostream> 3 #include<windows.h> 4 int calc() { 5 //当为无参数时,返回0值 6 return 0; 7 } 8 9 template <typename R1 ,typename...Args> 10 int calc(R1 a, Args...args) { 11 12 return a + calc(args...); 13 } 14 15 int main(int argc , char * args []) { 16 17 //使用函数指针 18 int(*fun) (int ,int ,int ,int ) = calc; 19 system("echo 使用函数指针实现1~4累加"); 20 std::cout << fun(1,2,3,4)<<std::endl; 21 //使用typedef来实现该功能 22 system("echo 使用typedef实现1~4累加"); 23 typedef int(*Add)(int, int, int); 24 Add Gadd = calc; 25 std::cout << Gadd(1, 2, 3) << std::endl; 26 //使用using别名来实现这么个功能 27 system("echo 使用using实现1~4累加"); 28 using Func = int(*) (int, int, int, int); 29 Func func = calc; 30 std::cout << func(1, 2, 3, 4) << std::endl; 31 std::cin.get(); 32 return 0; 33 }
效果图:
4. C++模板元编程:
对于模板元编程: 我的理解是,你所要的计算,在编译的时候,已经处理玩了,只需要在运行的时候输出结果即可!
当我们每每学到模板元编程的时候,就会有一个混淆的词汇出现,哒,看------函数式编程。 到底什么是函数式编程呢?
建议去看这篇文章,http://www.ruanyifeng.com/blog/2012/04/functional_programming.html 模板元编程用处广泛,
我们知道当硬件条件限制的情况下,除了优化算法,还有一种途径,那就是用模板元编程。 现在就让我们来看看这个金典的应用吧!
斐波那契数列的计算......
1 #include<iostream> 2 #include<time.h> 3 #include<windows.h> 4 /* 5 斐波那契数列 6 H(1)=H(0)=1; 7 H(N)= H(N-1)+H(N-2); 8 */ 9 using namespace std; 10 11 /* 普通版普通版 */ 12 using _int = long ; //使用别名 13 14 _int feibona(_int ac) { 15 if (ac == 0||ac==1) return 1; 16 return feibona(ac-1) +feibona(ac-2); 17 } 18 19 /* 使用元编程 完全特化版 方法如下*/ 20 template <_int N> 21 struct data { 22 //采用枚举 23 enum { res = data<N - 1>::res + data<N - 2>::res }; 24 }; 25 26 template <> 27 struct data<1> { 28 //采用枚举 29 enum { res = 1L }; 30 }; 31 32 template <> 33 struct data<0> { 34 //采用枚举 35 enum { res = 1L }; 36 }; 37 38 39 int main(int argc, char * args[]) { 40 41 time_t a ,b; 42 a = clock(); //开始记录时间 43 cout << data<45L>::res << endl; 44 b = clock(); //开始记录时间 45 system("echo 采用元编程所消耗的时间"); 46 cout << (double)(b - a) / CLK_TCK<<"ms"<<endl; 47 a = clock(); 48 cout << feibona(45L) << endl; 49 b = clock(); 50 system("echo 采用普通的算法所消耗的时间"); 51 cout << (double)(b - a) / CLK_TCK << "ms" << endl; 52 cin.get(); 53 return 0; 54 }
两者相对比的效果图:
C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法)
标签:
原文地址:http://www.cnblogs.com/gongxijun/p/4385838.html